From 358364b45e21585103017325e72a36b2de4d2b6a Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Apr 2019 11:23:08 +1000 Subject: [PATCH 0001/1299] stm32/boards/NUCLEO_L432KC: Disable complex nos and default frozen mods. To save space, since this board only hase 256k of flash. --- ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h | 1 + ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h index aa8c9e67448c1..7f2ebbad552be 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h @@ -3,6 +3,7 @@ #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_USOCKET (0) #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk index e8740d64adf35..46697348fe918 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk @@ -3,3 +3,6 @@ CMSIS_MCU = STM32L432xx AF_FILE = boards/stm32l432_af.csv LD_FILES = boards/stm32l432.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg + +# Don't include default frozen modules because MCU is tight on flash space +FROZEN_MPY_DIR ?= From d5f0c87bb985ae344014dc2041fbaad5c522f638 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Apr 2019 14:20:42 +1100 Subject: [PATCH 0002/1299] extmod/modlwip: Abort TCP conns that didn't close cleanly in a while. --- extmod/modlwip.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 7ebfa8904728c..e0bf17db8c4e2 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -57,6 +57,10 @@ #define DEBUG_printf(...) (void)0 #endif +// Timeout between closing a TCP socket and doing a tcp_abort on that +// socket, if the connection isn't closed cleanly in that time. +#define MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS (10000) + // All socket options should be globally distinct, // because we ignore option levels for efficiency. #define IP_ADD_MEMBERSHIP 0x400 @@ -1342,6 +1346,13 @@ STATIC mp_uint_t lwip_socket_write(mp_obj_t self_in, const void *buf, mp_uint_t return MP_STREAM_ERROR; } +STATIC err_t _lwip_tcp_close_poll(void *arg, struct tcp_pcb *pcb) { + // Connection has not been cleanly closed so just abort it to free up memory + tcp_poll(pcb, NULL, 0); + tcp_abort(pcb); + return ERR_OK; +} + STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; @@ -1401,6 +1412,8 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ } // Deregister callback (pcb.tcp is set to NULL below so must deregister now) + tcp_arg(socket->pcb.tcp, NULL); + tcp_err(socket->pcb.tcp, NULL); tcp_recv(socket->pcb.tcp, NULL); switch (socket->type) { @@ -1408,6 +1421,9 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ if (tcp_close(socket->pcb.tcp) != ERR_OK) { DEBUG_printf("lwip_close: had to call tcp_abort()\n"); tcp_abort(socket->pcb.tcp); + } else { + // If connection not cleanly closed after timeout then abort the connection + tcp_poll(socket->pcb.tcp, _lwip_tcp_close_poll, MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS / 500); } break; } From 46e5d6b8893e07538c33677a349e9e2fd038e62c Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 11 Apr 2019 12:09:21 +1000 Subject: [PATCH 0003/1299] stm32/rtc: Add auto-LSE-bypass detection with fallback to LSE then LSI. If MICROPY_HW_RTC_USE_BYPASS is enabled the RTC startup goes as follows: - RTC is started with LSE in bypass mode to begin with - if that fails to start (after a given timeout) then LSE is reconfigured in non-bypass - if that fails to start then RTC is switched to LSI --- ports/stm32/mpconfigboard_common.h | 6 +++ ports/stm32/rtc.c | 65 +++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 1ace8fcaf4160..08c835a1c2c43 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -210,6 +210,12 @@ #endif #endif +// If disabled then try normal (non-bypass) LSE first, with fallback to LSI. +// If enabled first try LSE in bypass mode. If that fails to start, try non-bypass mode, with fallback to LSI. +#ifndef MICROPY_HW_RTC_USE_BYPASS +#define MICROPY_HW_RTC_USE_BYPASS (0) +#endif + #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE // Provide block device macros if internal flash storage is enabled #define MICROPY_HW_BDEV_IOCTL flash_bdev_ioctl diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 250c34bcf5209..ec1e947b21540 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -61,11 +61,11 @@ static mp_uint_t rtc_info; #endif STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc); -STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse); +STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse, bool rtc_use_byp); STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc); STATIC void RTC_CalendarConfig(void); -#if defined(MICROPY_HW_RTC_USE_LSE) && MICROPY_HW_RTC_USE_LSE +#if MICROPY_HW_RTC_USE_LSE || MICROPY_HW_RTC_USE_BYPASS STATIC bool rtc_use_lse = true; #else STATIC bool rtc_use_lse = false; @@ -159,7 +159,7 @@ void rtc_init_start(bool force_init) { rtc_info &= ~0x01000000; } } - PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse); + PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse, MICROPY_HW_RTC_USE_BYPASS); } void rtc_init_finalise() { @@ -167,26 +167,34 @@ void rtc_init_finalise() { return; } - rtc_info = 0x20000000; - if (PYB_RTC_Init(&RTCHandle) != HAL_OK) { + rtc_info = 0; + while (PYB_RTC_Init(&RTCHandle) != HAL_OK) { if (rtc_use_lse) { - // fall back to LSI... - rtc_use_lse = false; + #if MICROPY_HW_RTC_USE_BYPASS + if (RCC->BDCR & RCC_BDCR_LSEBYP) { + // LSEBYP failed, fallback to LSE non-bypass + rtc_info |= 0x02000000; + } else + #endif + { + // LSE failed, fallback to LSI + rtc_use_lse = false; + rtc_info |= 0x01000000; + } rtc_startup_tick = HAL_GetTick(); - PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse); + PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse, false); HAL_PWR_EnableBkUpAccess(); RTCHandle.State = HAL_RTC_STATE_RESET; - if (PYB_RTC_Init(&RTCHandle) != HAL_OK) { - rtc_info = 0x0100ffff; // indicate error - return; - } } else { // init error - rtc_info = 0xffff; // indicate error + rtc_info |= 0xffff; // indicate error return; } } + // RTC started successfully + rtc_info = 0x20000000; + // record if LSE or LSI is used rtc_info |= (rtc_use_lse << 28); @@ -257,6 +265,16 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc } #endif + #if MICROPY_HW_RTC_USE_BYPASS + // If LSEBYP is enabled and new state is non-bypass then disable LSEBYP + if (RCC_OscInitStruct->LSEState == RCC_LSE_ON && (RCC->BDCR & RCC_BDCR_LSEBYP)) { + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); + while (RCC->BDCR & RCC_BDCR_LSERDY) { + } + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); + } + #endif + // Set the new LSE configuration __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); } @@ -327,7 +345,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) { } } -STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse) { +STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse, bool rtc_use_byp) { /* To change the source clock of the RTC feature (LSE, LSI), You have to: - Enable the power clock using __PWR_CLK_ENABLE() - Enable write access using HAL_PWR_EnableBkUpAccess() function before to @@ -342,12 +360,14 @@ STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; - if (rtc_use_lse) { - #if MICROPY_HW_RTC_USE_BYPASS + #if MICROPY_HW_RTC_USE_BYPASS + if (rtc_use_byp) { RCC_OscInitStruct.LSEState = RCC_LSE_BYPASS; - #else + RCC_OscInitStruct.LSIState = RCC_LSI_OFF; + } else + #endif + if (rtc_use_lse) { RCC_OscInitStruct.LSEState = RCC_LSE_ON; - #endif RCC_OscInitStruct.LSIState = RCC_LSI_OFF; } else { RCC_OscInitStruct.LSEState = RCC_LSE_OFF; @@ -361,14 +381,21 @@ STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse) { #define PYB_LSE_TIMEOUT_VALUE 1000 // ST docs spec 2000 ms LSE startup, seems to be too pessimistic #define PYB_LSI_TIMEOUT_VALUE 500 // this is way too pessimistic, typ. < 1ms +#define PYB_BYP_TIMEOUT_VALUE 150 STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc) { // we already had a kick so now wait for the corresponding ready state... if (rtc_use_lse) { // we now have to wait for LSE ready or timeout + uint32_t timeout = PYB_LSE_TIMEOUT_VALUE; + #if MICROPY_HW_RTC_USE_BYPASS + if (RCC->BDCR & RCC_BDCR_LSEBYP) { + timeout = PYB_BYP_TIMEOUT_VALUE; + } + #endif uint32_t tickstart = rtc_startup_tick; while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) { - if ((HAL_GetTick() - tickstart ) > PYB_LSE_TIMEOUT_VALUE) { + if ((HAL_GetTick() - tickstart ) > timeout) { return HAL_TIMEOUT; } } From fc9f2ff0cdc3cc75732d7954ac012b5a25f20f10 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 11 Apr 2019 12:14:21 +1000 Subject: [PATCH 0004/1299] stm32/rtc: Remove unused LSE detection code. --- ports/stm32/rtc.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index ec1e947b21540..8e56e25f9ff93 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -73,36 +73,6 @@ STATIC bool rtc_use_lse = false; STATIC uint32_t rtc_startup_tick; STATIC bool rtc_need_init_finalise = false; -// check if LSE exists -// not well tested, should probably be removed -STATIC bool lse_magic(void) { -#if 0 - uint32_t mode_in = GPIOC->MODER & 0x3fffffff; - uint32_t mode_out = mode_in | 0x40000000; - GPIOC->MODER = mode_out; - GPIOC->OTYPER &= 0x7fff; - GPIOC->BSRRH = 0x8000; - GPIOC->OSPEEDR &= 0x3fffffff; - GPIOC->PUPDR &= 0x3fffffff; - int i = 0xff0; - __IO int d = 0; - uint32_t tc = 0; - __IO uint32_t j; - while (i) { - GPIOC->MODER = mode_out; - GPIOC->MODER = mode_in; - for (j = 0; j < d; j++) ; - i--; - if ((GPIOC->IDR & 0x8000) == 0) { - tc++; - } - } - return (tc < 0xff0)?true:false; -#else - return false; -#endif -} - void rtc_init_start(bool force_init) { RTCHandle.Instance = RTC; @@ -152,13 +122,6 @@ void rtc_init_start(bool force_init) { rtc_startup_tick = HAL_GetTick(); rtc_info = 0x3f000000 | (rtc_startup_tick & 0xffffff); - if (rtc_use_lse) { - if (lse_magic()) { - // don't even try LSE - rtc_use_lse = false; - rtc_info &= ~0x01000000; - } - } PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse, MICROPY_HW_RTC_USE_BYPASS); } From 3c9f78b048fade80f71cca25999ee2541a80034e Mon Sep 17 00:00:00 2001 From: Damiano Mazzella Date: Sat, 6 Apr 2019 23:24:55 +0200 Subject: [PATCH 0005/1299] zephyr/CMakeLists.txt: Set AR to point to the Zephyr toolchain exe. --- ports/zephyr/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/zephyr/CMakeLists.txt b/ports/zephyr/CMakeLists.txt index 8e01624170bb9..017b0689cef58 100644 --- a/ports/zephyr/CMakeLists.txt +++ b/ports/zephyr/CMakeLists.txt @@ -17,6 +17,7 @@ zephyr_get_compile_options_for_lang_as_string(C options) add_custom_target( outputexports COMMAND echo CC="${CMAKE_C_COMPILER}" + COMMAND echo AR="${CMAKE_AR}" COMMAND echo Z_CFLAGS=${system_includes} ${includes} ${definitions} ${options} VERBATIM USES_TERMINAL From fd112239d6b7e6ebeb78f62e3b02aa6640a88772 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Apr 2019 11:31:22 +1000 Subject: [PATCH 0006/1299] stm32/rtc: Remove non-ASCII mu-character from source code comment. And fix a typo in the comment on this line. --- ports/stm32/rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 8e56e25f9ff93..4b9fbbda525da 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -52,7 +52,7 @@ static mp_uint_t rtc_info; // Note: LSI is around (32KHz), these dividers should work either way // ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1) // modify RTC_ASYNCH_PREDIV & RTC_SYNCH_PREDIV in board//mpconfigport.h to change sub-second ticks -// default is 3906.25 µs, min is ~30.52 µs (will increas Ivbat by ~500nA) +// default is 3906.25 us, min is ~30.52 us (will increase Ivbat by ~500nA) #ifndef RTC_ASYNCH_PREDIV #define RTC_ASYNCH_PREDIV (0x7f) #endif From 673e154dfef6aef827b86ea177c211269358b282 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Apr 2019 11:34:52 +1000 Subject: [PATCH 0007/1299] py/makedefs: Use io.open with utf-8 encoding when processing source. In case (user) source code contains utf-8 encoded data and the default locale is not utf-8. See #4592. --- py/makemoduledefs.py | 3 ++- py/makeqstrdefs.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/py/makemoduledefs.py b/py/makemoduledefs.py index 18d327f002971..f17b0e38dfcbc 100644 --- a/py/makemoduledefs.py +++ b/py/makemoduledefs.py @@ -8,6 +8,7 @@ from __future__ import print_function import re +import io import os import argparse @@ -49,7 +50,7 @@ def find_module_registrations(c_file): # No c file to match the object file, skip return set() - with open(c_file) as c_file_obj: + with io.open(c_file, encoding='utf-8') as c_file_obj: return set(re.findall(pattern, c_file_obj.read())) diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 176440136df8f..457bdeef65dbf 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -9,6 +9,7 @@ import re import sys +import io import os # Blacklist of qstrings that are specially handled in further @@ -108,7 +109,7 @@ class Args: pass if args.command == "split": - with open(args.input_filename) as infile: + with io.open(args.input_filename, encoding='utf-8') as infile: process_file(infile) if args.command == "cat": From 1754c71f45b6c56b55f5e9e0bb7e77c8083c96bb Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 14 Apr 2019 23:32:53 +1000 Subject: [PATCH 0008/1299] py/runtime: Optimise to not create temp float for int to power negative. --- py/runtime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/py/runtime.c b/py/runtime.c index 75d50596e474f..9210070de3d24 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -456,8 +456,7 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_INPLACE_POWER: if (rhs_val < 0) { #if MICROPY_PY_BUILTINS_FLOAT - lhs = mp_obj_new_float(lhs_val); - goto generic_binary_op; + return mp_obj_float_binary_op(op, lhs_val, rhs); #else mp_raise_ValueError("negative power with no float support"); #endif From 3fa06cf61e6a94417402c4a074e326ccea9cd9d8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 15 Apr 2019 11:14:22 +1000 Subject: [PATCH 0009/1299] py/objset: Remove unused forward declaration and clean up whitespace. --- py/objset.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/py/objset.c b/py/objset.c index 88e9d5cc6f2e4..6f5bcc032a9a5 100644 --- a/py/objset.c +++ b/py/objset.c @@ -45,8 +45,6 @@ typedef struct _mp_obj_set_it_t { size_t cur; } mp_obj_set_it_t; -STATIC mp_obj_t set_it_iternext(mp_obj_t self_in); - STATIC bool is_set_or_frozenset(mp_obj_t o) { return mp_obj_is_type(o, &mp_type_set) #if MICROPY_PY_BUILTINS_FROZENSET @@ -154,7 +152,6 @@ STATIC mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) { return MP_OBJ_FROM_PTR(o); } - /******************************************************************************/ /* set methods */ @@ -169,9 +166,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add); STATIC mp_obj_t set_clear(mp_obj_t self_in) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); - mp_set_clear(&self->set); - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear); @@ -332,6 +327,7 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool } return out; } + STATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(self_in, other_in, false); } @@ -518,7 +514,6 @@ STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { /******************************************************************************/ /* set constructors & public C API */ - STATIC const mp_rom_map_elem_t set_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&set_add_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&set_clear_obj) }, @@ -539,7 +534,6 @@ STATIC const mp_rom_map_elem_t set_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&set_update_obj) }, { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) }, }; - STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); const mp_obj_type_t mp_type_set = { From 9ce25d70220853faee5c817f9e8d75e265cf73ee Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 15 Apr 2019 11:30:19 +1000 Subject: [PATCH 0010/1299] py/runtime: Fix mp_unpack_ex so seq can't be reclaimed by GC during use. The issue described in the comment added here can be seen by forcing a gc_collect() at the start of each call to gc_alloc(). --- py/runtime.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/py/runtime.c b/py/runtime.c index 9210070de3d24..a3628eecb45a2 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -875,8 +875,12 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) { DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right); size_t seq_len; if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) { + // Make the seq variable volatile so the compiler keeps a reference to it, + // since if it's a tuple then seq_items points to the interior of the GC cell + // and mp_obj_new_list may trigger a GC which doesn't trace this and reclaims seq. + volatile mp_obj_t seq = seq_in; mp_obj_t *seq_items; - mp_obj_get_array(seq_in, &seq_len, &seq_items); + mp_obj_get_array(seq, &seq_len, &seq_items); if (seq_len < num_left + num_right) { goto too_short; } @@ -887,6 +891,7 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) { for (size_t i = 0; i < num_left; i++) { items[num_right + 1 + i] = seq_items[num_left - 1 - i]; } + seq = MP_OBJ_NULL; } else { // Generic iterable; this gets a bit messy: we unpack known left length to the // items destination array, then the rest to a dynamically created list. Once the From 194d6b6788e73216b9c0b60ced0b9ade1b0cb2dd Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 15 Apr 2019 11:41:03 +1000 Subject: [PATCH 0011/1299] stm32/timer: Correctly initialise extended break settings on F7/H7/L4. Fixes issue #4693. --- ports/stm32/timer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index b3bb92f2e5ad1..7f4c0d85a9547 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -476,6 +476,12 @@ STATIC void config_deadtime(pyb_timer_obj_t *self, mp_int_t ticks, mp_int_t brk) deadTimeConfig.DeadTime = compute_dtg_from_ticks(ticks); deadTimeConfig.BreakState = brk == BRK_OFF ? TIM_BREAK_DISABLE : TIM_BREAK_ENABLE; deadTimeConfig.BreakPolarity = brk == BRK_LOW ? TIM_BREAKPOLARITY_LOW : TIM_BREAKPOLARITY_HIGH; + #if defined(STM32F7) || defined(STM32H7) | defined(STM32L4) + deadTimeConfig.BreakFilter = 0; + deadTimeConfig.Break2State = TIM_BREAK_DISABLE; + deadTimeConfig.Break2Polarity = TIM_BREAKPOLARITY_LOW; + deadTimeConfig.Break2Filter = 0; + #endif deadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; HAL_TIMEx_ConfigBreakDeadTime(&self->tim, &deadTimeConfig); } From fd58136d6bffe422f4afb6bc08973ecfb6ff8f1d Mon Sep 17 00:00:00 2001 From: Daniel O'Connor Date: Sat, 13 Apr 2019 21:27:22 +0930 Subject: [PATCH 0012/1299] docs/cmodules: Fix example to globally define MODULE_EXAMPLE_ENABLED. MODULE_EXAMPLE_ENABLED must be globally defined for the module to be seen and referenced by all parts of the code. --- docs/develop/cmodules.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index 919f518242bc9..5c0b498ff506f 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -71,8 +71,6 @@ Directory:: #include "py/runtime.h" #include "py/builtin.h" - #define MODULE_EXAMPLE_ENABLED (1) - // This is the function which will be called from Python as example.add_ints(a, b). STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) { // Extract the ints from the micropython input objects @@ -119,6 +117,14 @@ Directory:: # This is not actually needed in this example. CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR) +Finally you will need to modify the ``mpconfigboard.h`` for your board +to tell the build process to include the new module by adding the +following + +.. code-block:: c + + #define MODULE_EXAMPLE_ENABLED (1) + Compiling the cmodule into MicroPython -------------------------------------- From a6e5846ba75d20df1795f75423535d9bc280c804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 11 Apr 2019 11:03:05 +0200 Subject: [PATCH 0013/1299] extmod/modurandom: Add init method to seed the Yasmarang generator. In CPython the random module is seeded differently on each import, and so this new macro option MICROPY_PY_URANDOM_SEED_INIT_FUNC allows to implement such a behaviour. --- extmod/modurandom.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/extmod/modurandom.c b/extmod/modurandom.c index 1512a3fd4a996..2e667570d65ce 100644 --- a/extmod/modurandom.c +++ b/extmod/modurandom.c @@ -200,8 +200,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_uniform_obj, mod_urandom_uniform); #endif // MICROPY_PY_URANDOM_EXTRA_FUNCS +#ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC +STATIC mp_obj_t mod_urandom___init__() { + mod_urandom_seed(MP_OBJ_NEW_SMALL_INT(MICROPY_PY_URANDOM_SEED_INIT_FUNC)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom___init___obj, mod_urandom___init__); +#endif + STATIC const mp_rom_map_elem_t mp_module_urandom_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_urandom) }, + #ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC + { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&mod_urandom___init___obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_getrandbits), MP_ROM_PTR(&mod_urandom_getrandbits_obj) }, { MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_urandom_seed_obj) }, #if MICROPY_PY_URANDOM_EXTRA_FUNCS From d4e182039f61979b22071274149b0ffcea17c370 Mon Sep 17 00:00:00 2001 From: Daniel O'Connor Date: Mon, 15 Apr 2019 14:31:15 +0930 Subject: [PATCH 0014/1299] docs/cmodules: Note the various ways MODULE_EXAMPLE_ENABLED can be set. --- docs/develop/cmodules.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index 5c0b498ff506f..ba43c3dc93cb1 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -117,14 +117,19 @@ Directory:: # This is not actually needed in this example. CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR) -Finally you will need to modify the ``mpconfigboard.h`` for your board -to tell the build process to include the new module by adding the -following +Finally you will need to define ``MODULE_EXAMPLE_ENABLED`` to 1. This +can be done by adding ``CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1`` to +the ``make`` command, or editing ``mpconfigport.h`` or +``mpconfigboard.h`` to add .. code-block:: c #define MODULE_EXAMPLE_ENABLED (1) +Note that the exact method depends on the port as they have different +structures. If not done correctly it will compile but importing will +fail to find the module. + Compiling the cmodule into MicroPython -------------------------------------- @@ -152,7 +157,7 @@ Building for stm32 port: .. code-block:: bash cd my_project/micropython/ports/stm32 - make USER_C_MODULES=../../../modules all + make USER_C_MODULES=../../../modules CFLAGS_EXTRA=-DMODULE_EXAMPLE_ENABLED=1 all Module usage in MicroPython From 4ce0091449052daca592f852a31eece074d34a57 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Apr 2019 14:16:11 +1000 Subject: [PATCH 0015/1299] esp32/README: Add info about pyparsing and the correct Python version. See issue #4655. --- ports/esp32/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/esp32/README.md b/ports/esp32/README.md index 0e6531db820cf..cd3d5af198407 100644 --- a/ports/esp32/README.md +++ b/ports/esp32/README.md @@ -48,12 +48,12 @@ If you use WSL then follow the [Linux guidelines](https://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html) for the ESP-IDF instead of the Windows ones. -The Espressif ESP-IDF instructions above only install pyserial for Python 2, -so if you're running Python 3 or a non-system Python you'll also need to -install `pyserial` (or `esptool`) so that the Makefile can flash the board -and set parameters: +You will also need either Python 2 or Python 3, along with the `pyserial` and +`pyparsing` packages installed for the version of Python that you will be using +(when building you can use, eg, `make PYTHON=python2` to specify the version +used). To install the required packages do: ```bash -$ pip install pyserial +$ pip install pyserial pyparsing ``` Once everything is set up you should have a functioning toolchain with From eb1f81b209f0d13059ebb4fa2ed105a0d6a4b0d0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Apr 2019 14:34:12 +1000 Subject: [PATCH 0016/1299] tests/micropython: Add some tests for failed heap allocation. This adds tests for some locations in the code where a memory allocation should raise an exception. --- tests/micropython/heapalloc_fail_bytearray.py | 90 +++++++++++++++++++ .../heapalloc_fail_bytearray.py.exp | 11 +++ tests/micropython/heapalloc_fail_dict.py | 21 +++++ tests/micropython/heapalloc_fail_dict.py.exp | 2 + tests/micropython/heapalloc_fail_list.py | 36 ++++++++ tests/micropython/heapalloc_fail_list.py.exp | 4 + .../micropython/heapalloc_fail_memoryview.py | 25 ++++++ .../heapalloc_fail_memoryview.py.exp | 2 + tests/micropython/heapalloc_fail_set.py | 21 +++++ tests/micropython/heapalloc_fail_set.py.exp | 2 + tests/micropython/heapalloc_fail_tuple.py | 12 +++ tests/micropython/heapalloc_fail_tuple.py.exp | 1 + 12 files changed, 227 insertions(+) create mode 100644 tests/micropython/heapalloc_fail_bytearray.py create mode 100644 tests/micropython/heapalloc_fail_bytearray.py.exp create mode 100644 tests/micropython/heapalloc_fail_dict.py create mode 100644 tests/micropython/heapalloc_fail_dict.py.exp create mode 100644 tests/micropython/heapalloc_fail_list.py create mode 100644 tests/micropython/heapalloc_fail_list.py.exp create mode 100644 tests/micropython/heapalloc_fail_memoryview.py create mode 100644 tests/micropython/heapalloc_fail_memoryview.py.exp create mode 100644 tests/micropython/heapalloc_fail_set.py create mode 100644 tests/micropython/heapalloc_fail_set.py.exp create mode 100644 tests/micropython/heapalloc_fail_tuple.py create mode 100644 tests/micropython/heapalloc_fail_tuple.py.exp diff --git a/tests/micropython/heapalloc_fail_bytearray.py b/tests/micropython/heapalloc_fail_bytearray.py new file mode 100644 index 0000000000000..fbf585c7f131f --- /dev/null +++ b/tests/micropython/heapalloc_fail_bytearray.py @@ -0,0 +1,90 @@ +# test handling of failed heap allocation with bytearray + +import micropython + +class GetSlice: + def __getitem__(self, idx): + return idx +sl = GetSlice()[:] + +# create bytearray +micropython.heap_lock() +try: + bytearray(4) +except MemoryError: + print('MemoryError: bytearray create') +micropython.heap_unlock() + +# create bytearray from bytes +micropython.heap_lock() +try: + bytearray(b'0123') +except MemoryError: + print('MemoryError: bytearray create from bytes') +micropython.heap_unlock() + +# create bytearray from iterator +r = range(4) +micropython.heap_lock() +try: + bytearray(r) +except MemoryError: + print('MemoryError: bytearray create from iter') +micropython.heap_unlock() + +# bytearray add +b = bytearray(4) +micropython.heap_lock() +try: + b + b'01' +except MemoryError: + print('MemoryError: bytearray.__add__') +micropython.heap_unlock() + +# bytearray iadd +b = bytearray(4) +micropython.heap_lock() +try: + b += b'01234567' +except MemoryError: + print('MemoryError: bytearray.__iadd__') +micropython.heap_unlock() +print(b) + +# bytearray append +b = bytearray(4) +micropython.heap_lock() +try: + for i in range(100): + b.append(1) +except MemoryError: + print('MemoryError: bytearray.append') +micropython.heap_unlock() + +# bytearray extend +b = bytearray(4) +micropython.heap_lock() +try: + b.extend(b'01234567') +except MemoryError: + print('MemoryError: bytearray.extend') +micropython.heap_unlock() + +# bytearray get with slice +b = bytearray(4) +micropython.heap_lock() +try: + b[sl] +except MemoryError: + print('MemoryError: bytearray subscr get') +micropython.heap_unlock() + +# extend bytearray using slice subscr +b = bytearray(4) +micropython.heap_lock() +try: + b[sl] = b'01234567' +except MemoryError: + print('MemoryError: bytearray subscr grow') +micropython.heap_unlock() +print(b) diff --git a/tests/micropython/heapalloc_fail_bytearray.py.exp b/tests/micropython/heapalloc_fail_bytearray.py.exp new file mode 100644 index 0000000000000..57f6202f5e9e8 --- /dev/null +++ b/tests/micropython/heapalloc_fail_bytearray.py.exp @@ -0,0 +1,11 @@ +MemoryError: bytearray create +MemoryError: bytearray create from bytes +MemoryError: bytearray create from iter +MemoryError: bytearray.__add__ +MemoryError: bytearray.__iadd__ +bytearray(b'\x00\x00\x00\x00') +MemoryError: bytearray.append +MemoryError: bytearray.extend +MemoryError: bytearray subscr get +MemoryError: bytearray subscr grow +bytearray(b'\x00\x00\x00\x00') diff --git a/tests/micropython/heapalloc_fail_dict.py b/tests/micropython/heapalloc_fail_dict.py new file mode 100644 index 0000000000000..ba872bfeb627f --- /dev/null +++ b/tests/micropython/heapalloc_fail_dict.py @@ -0,0 +1,21 @@ +# test handling of failed heap allocation with dict + +import micropython + +# create dict +x = 1 +micropython.heap_lock() +try: + {x:x} +except MemoryError: + print('MemoryError: create dict') +micropython.heap_unlock() + +# create dict view +x = {1:1} +micropython.heap_lock() +try: + x.items() +except MemoryError: + print('MemoryError: dict.items') +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_fail_dict.py.exp b/tests/micropython/heapalloc_fail_dict.py.exp new file mode 100644 index 0000000000000..70cfc64ba43ff --- /dev/null +++ b/tests/micropython/heapalloc_fail_dict.py.exp @@ -0,0 +1,2 @@ +MemoryError: create dict +MemoryError: dict.items diff --git a/tests/micropython/heapalloc_fail_list.py b/tests/micropython/heapalloc_fail_list.py new file mode 100644 index 0000000000000..a54bdb6cf6a5a --- /dev/null +++ b/tests/micropython/heapalloc_fail_list.py @@ -0,0 +1,36 @@ +# test handling of failed heap allocation with list + +import micropython + +class GetSlice: + def __getitem__(self, idx): + return idx +sl = GetSlice()[:] + +# create slice in VM +l = [1, 2, 3] +micropython.heap_lock() +try: + print(l[0:1]) +except MemoryError: + print('MemoryError: list index') +micropython.heap_unlock() + +# get from list using slice +micropython.heap_lock() +try: + l[sl] +except MemoryError: + print('MemoryError: list get slice') +micropython.heap_unlock() + +# extend list using slice subscr +l = [1, 2] +l2 = [3, 4, 5, 6, 7, 8, 9, 10] +micropython.heap_lock() +try: + l[sl] = l2 +except MemoryError: + print('MemoryError: list extend slice') +micropython.heap_unlock() +print(l) diff --git a/tests/micropython/heapalloc_fail_list.py.exp b/tests/micropython/heapalloc_fail_list.py.exp new file mode 100644 index 0000000000000..0e1637476b97d --- /dev/null +++ b/tests/micropython/heapalloc_fail_list.py.exp @@ -0,0 +1,4 @@ +MemoryError: list index +MemoryError: list get slice +MemoryError: list extend slice +[1, 2] diff --git a/tests/micropython/heapalloc_fail_memoryview.py b/tests/micropython/heapalloc_fail_memoryview.py new file mode 100644 index 0000000000000..3ba9015ff113e --- /dev/null +++ b/tests/micropython/heapalloc_fail_memoryview.py @@ -0,0 +1,25 @@ +# test handling of failed heap allocation with memoryview + +import micropython + +class GetSlice: + def __getitem__(self, idx): + return idx +sl = GetSlice()[:] + +# create memoryview +micropython.heap_lock() +try: + memoryview(b'') +except MemoryError: + print('MemoryError: memoryview create') +micropython.heap_unlock() + +# memoryview get with slice +m = memoryview(b'') +micropython.heap_lock() +try: + m[sl] +except MemoryError: + print('MemoryError: memoryview subscr get') +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_fail_memoryview.py.exp b/tests/micropython/heapalloc_fail_memoryview.py.exp new file mode 100644 index 0000000000000..e41a1e6cb2a75 --- /dev/null +++ b/tests/micropython/heapalloc_fail_memoryview.py.exp @@ -0,0 +1,2 @@ +MemoryError: memoryview create +MemoryError: memoryview subscr get diff --git a/tests/micropython/heapalloc_fail_set.py b/tests/micropython/heapalloc_fail_set.py new file mode 100644 index 0000000000000..98e615d64adfb --- /dev/null +++ b/tests/micropython/heapalloc_fail_set.py @@ -0,0 +1,21 @@ +# test handling of failed heap allocation with set + +import micropython + +# create set +x = 1 +micropython.heap_lock() +try: + {x,} +except MemoryError: + print('MemoryError: set create') +micropython.heap_unlock() + +# set copy +s = {1, 2} +micropython.heap_lock() +try: + s.copy() +except MemoryError: + print('MemoryError: set copy') +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_fail_set.py.exp b/tests/micropython/heapalloc_fail_set.py.exp new file mode 100644 index 0000000000000..dd749672dcc38 --- /dev/null +++ b/tests/micropython/heapalloc_fail_set.py.exp @@ -0,0 +1,2 @@ +MemoryError: set create +MemoryError: set copy diff --git a/tests/micropython/heapalloc_fail_tuple.py b/tests/micropython/heapalloc_fail_tuple.py new file mode 100644 index 0000000000000..1cd23fb74bce3 --- /dev/null +++ b/tests/micropython/heapalloc_fail_tuple.py @@ -0,0 +1,12 @@ +# test handling of failed heap allocation with tuple + +import micropython + +# create tuple +x = 1 +micropython.heap_lock() +try: + (x,) +except MemoryError: + print('MemoryError: tuple create') +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_fail_tuple.py.exp b/tests/micropython/heapalloc_fail_tuple.py.exp new file mode 100644 index 0000000000000..5bf632d799cb8 --- /dev/null +++ b/tests/micropython/heapalloc_fail_tuple.py.exp @@ -0,0 +1 @@ +MemoryError: tuple create From f1774fa049afc6f35192ff0f60ac5486cd9d3b08 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Apr 2019 15:36:59 +1000 Subject: [PATCH 0017/1299] stm32/system_stm32f0: Enable PWR clock on startup. To be consistent with how F4/F7/H7/L4 works in system_stm32.c. The power control peripheral is needed at least for the RTC. --- ports/stm32/system_stm32f0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/stm32/system_stm32f0.c b/ports/stm32/system_stm32f0.c index 9d4b06e56821d..afabdb667f8fc 100644 --- a/ports/stm32/system_stm32f0.c +++ b/ports/stm32/system_stm32f0.c @@ -129,6 +129,9 @@ void SystemInit(void) { } void SystemClock_Config(void) { + // Enable power control peripheral + __HAL_RCC_PWR_CLK_ENABLE(); + // Set flash latency to 1 because SYSCLK > 24MHz FLASH->ACR = (FLASH->ACR & ~0x7) | 0x1; From 11657f2f20c869212364efa8633a7870c9be0c3c Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Apr 2019 15:59:47 +1000 Subject: [PATCH 0018/1299] stm32/system_stm32f0: Add support for using HSE and PLL as SYSCLK. To configure the SYSCLK on an F0 enable one of: MICROPY_HW_CLK_USE_HSI48 MICROPY_HW_CLK_USE_HSE MICROPY_HW_CLK_USE_BYPASS --- .../boards/NUCLEO_F091RC/mpconfigboard.h | 1 + ports/stm32/system_stm32f0.c | 31 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h index 5e67916cbc80d..e1802da2dac1d 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h @@ -17,6 +17,7 @@ #define MICROPY_HW_HAS_SWITCH (1) // For system clock, board uses internal 48MHz, HSI48 +#define MICROPY_HW_CLK_USE_HSI48 (1) // The board has an external 32kHz crystal #define MICROPY_HW_RTC_USE_LSE (1) diff --git a/ports/stm32/system_stm32f0.c b/ports/stm32/system_stm32f0.c index afabdb667f8fc..c3c675c7459a7 100644 --- a/ports/stm32/system_stm32f0.c +++ b/ports/stm32/system_stm32f0.c @@ -40,7 +40,7 @@ ****************************************************************************** */ -#include STM32_HAL_H +#include "py/mphal.h" #ifndef HSE_VALUE #define HSE_VALUE (8000000) @@ -135,12 +135,37 @@ void SystemClock_Config(void) { // Set flash latency to 1 because SYSCLK > 24MHz FLASH->ACR = (FLASH->ACR & ~0x7) | 0x1; + #if MICROPY_HW_CLK_USE_HSI48 // Use the 48MHz internal oscillator + RCC->CR2 |= RCC_CR2_HSI48ON; while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) { } - RCC->CFGR |= 3 << RCC_CFGR_SW_Pos; - while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != 0x03) { + const uint32_t sysclk_src = 3; + + #else + // Use HSE and the PLL to get a 48MHz SYSCLK + + #if MICROPY_HW_CLK_USE_BYPASS + RCC->CR |= RCC_CR_HSEBYP; + #endif + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) { + // Wait for HSE to be ready + } + RCC->CFGR = ((48000000 / HSE_VALUE) - 2) << RCC_CFGR_PLLMUL_Pos | 2 << RCC_CFGR_PLLSRC_Pos; + RCC->CFGR2 = 0; // Input clock not divided + RCC->CR |= RCC_CR_PLLON; // Turn PLL on + while ((RCC->CR & RCC_CR_PLLRDY) == 0) { + // Wait for PLL to lock + } + const uint32_t sysclk_src = 2; + + #endif + + // Select SYSCLK source + RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { // Wait for SYSCLK source to change } From 8402c26cfa98b4689f5ac4673952a654cfe5b678 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 18 Apr 2019 17:15:11 +1000 Subject: [PATCH 0019/1299] stm32/powerctrl: Enable EIWUP to ensure RTC wakes device from standby. --- ports/stm32/powerctrl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 165919977fe3c..669e568f8a2d6 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -390,6 +390,12 @@ void powerctrl_enter_standby_mode(void) { // enable previously-enabled RTC interrupts RTC->CR |= save_irq_bits; + #if defined(STM32F7) + // Enable the internal (eg RTC) wakeup sources + // See Errata 2.2.2 "Wakeup from Standby mode when the back-up SRAM regulator is enabled" + PWR->CSR1 |= PWR_CSR1_EIWUP; + #endif + // enter standby mode HAL_PWR_EnterSTANDBYMode(); // we never return; MCU is reset on exit from standby From 27d22d8712d79636be7115d47c8872d6c1da749c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 19 Apr 2019 17:38:27 +1000 Subject: [PATCH 0020/1299] py/mpprint: Support printing %ld and %lu formats on 64-bit archs. Fixes issue #4702. --- py/mpprint.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/py/mpprint.c b/py/mpprint.c index 82e78f62fae9b..cf09f7bbe2ccd 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -503,22 +503,28 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { chrs += mp_print_strn(print, str, prec, flags, fill, width); break; } - case 'u': - chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 10, 'a', flags, fill, width); - break; - case 'd': - chrs += mp_print_int(print, va_arg(args, int), 1, 10, 'a', flags, fill, width); + case 'd': { + mp_int_t val; + if (long_arg) { + val = va_arg(args, long int); + } else { + val = va_arg(args, int); + } + chrs += mp_print_int(print, val, 1, 10, 'a', flags, fill, width); break; + } + case 'u': case 'x': case 'X': { - char fmt_c = *fmt - 'X' + 'A'; + int base = 16 - ((*fmt + 1) & 6); // maps char u/x/X to base 10/16/16 + char fmt_c = (*fmt & 0xf0) - 'P' + 'A'; // maps char u/x/X to char a/a/A mp_uint_t val; if (long_arg) { val = va_arg(args, unsigned long int); } else { val = va_arg(args, unsigned int); } - chrs += mp_print_int(print, val, 0, 16, fmt_c, flags, fill, width); + chrs += mp_print_int(print, val, 0, base, fmt_c, flags, fill, width); break; } case 'p': From aa7b32c81136b1250d9515adf9d13eefd81e86d4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 24 Apr 2019 15:51:19 +1000 Subject: [PATCH 0021/1299] stm32/dac: Rework DAC driver to use direct register access. This patch makes the DAC driver simpler and removes the need for the ST HAL. As part of it, new helper functions are added to the DMA driver, which also use direct register access instead of the ST HAL. Main changes to the DAC interface are: - The DAC uPy object is no longer allocated dynamically on the heap, rather it's statically allocated and the same object is retrieved for subsequent uses of pyb.DAC(). This allows to access the DAC objects without resetting the DAC peripheral. It also means that the DAC is only reset if explicitly passed initialisation parameters, like "bits" or "buffering". - The DAC.noise() and DAC.triangle() methods now output a signal which is full scale (previously it was a fraction of the full output voltage). - The DAC.write_timed() method is fixed so that it continues in the background when another peripheral (eg SPI) uses the DMA (previously the DAC would stop if another peripheral finished with the DMA and shut the DMA peripheral off completely). Based on the above, the following backwards incompatibilities are introduced: - pyb.DAC(id) will now only reset the DAC the first time it is called, whereas previously each call to create a DAC object would reset the DAC. To get the old behaviour pass the bits parameter like: pyb.DAC(id, bits). - DAC.noise() and DAC.triangle() are now full scale. To get previous behaviour (to change the amplitude and offset) write to the DAC_CR (MAMP bits) and DAC_DHR12Rx registers manually. --- ports/stm32/Makefile | 2 - ports/stm32/dac.c | 296 ++++++++++++++++++------------------------- ports/stm32/dac.h | 2 - ports/stm32/dma.c | 100 ++++++++++++++- ports/stm32/dma.h | 4 + ports/stm32/main.c | 4 - 6 files changed, 226 insertions(+), 182 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 242ced38cb4d4..d90a7c2e4f2db 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -296,8 +296,6 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_adc.c \ hal_adc_ex.c \ hal_cortex.c \ - hal_dac.c \ - hal_dac_ex.c \ hal_dma.c \ hal_flash.c \ hal_flash_ex.c \ diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index 3a92258ffb994..cb9157c3daa97 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -70,15 +70,6 @@ #define DAC DAC1 #endif -STATIC DAC_HandleTypeDef DAC_Handle; - -void dac_init(void) { - memset(&DAC_Handle, 0, sizeof DAC_Handle); - DAC_Handle.Instance = DAC; - DAC_Handle.State = HAL_DAC_STATE_RESET; - HAL_DAC_Init(&DAC_Handle); -} - #if defined(TIM6) STATIC void TIM6_Config(uint freq) { // Init TIM6 at the required frequency (in Hz) @@ -131,27 +122,97 @@ STATIC uint32_t TIMx_Config(mp_obj_t timer) { } } +STATIC void dac_deinit(uint32_t dac_channel) { + DAC->CR &= ~(DAC_CR_EN1 << dac_channel); + #if defined(STM32H7) || defined(STM32L4) + DAC->MCR = (DAC->MCR & ~(DAC_MCR_MODE1_Msk << dac_channel)) | (DAC_OUTPUTBUFFER_DISABLE << dac_channel); + #else + DAC->CR |= DAC_CR_BOFF1 << dac_channel; + #endif +} + +STATIC void dac_config_channel(uint32_t dac_channel, uint32_t trig, uint32_t outbuf) { + DAC->CR &= ~(DAC_CR_EN1 << dac_channel); + uint32_t cr_off = DAC_CR_DMAEN1 | DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1; + uint32_t cr_on = trig; + #if defined(STM32H7) || defined(STM32L4) + DAC->MCR = (DAC->MCR & ~(DAC_MCR_MODE1_Msk << dac_channel)) | (outbuf << dac_channel); + #else + cr_off |= DAC_CR_BOFF1; + cr_on |= outbuf; + #endif + DAC->CR = (DAC->CR & ~(cr_off << dac_channel)) | (cr_on << dac_channel); +} + +STATIC void dac_set_value(uint32_t dac_channel, uint32_t align, uint32_t value) { + uint32_t base; + if (dac_channel == DAC_CHANNEL_1) { + base = (uint32_t)&DAC->DHR12R1; + } else { + base = (uint32_t)&DAC->DHR12R2; + } + *(volatile uint32_t*)(base + align) = value; +} + +STATIC void dac_start(uint32_t dac_channel) { + DAC->CR |= DAC_CR_EN1 << dac_channel; +} + +STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, uint32_t dma_mode, uint32_t bit_size, uint32_t dac_align, size_t len, void *buf) { + uint32_t dma_align; + if (bit_size == 8) { + dma_align = DMA_MDATAALIGN_BYTE | DMA_PDATAALIGN_BYTE; + } else { + dma_align = DMA_MDATAALIGN_HALFWORD | DMA_PDATAALIGN_HALFWORD; + } + + uint32_t base; + if (dac_channel == DAC_CHANNEL_1) { + base = (uint32_t)&DAC->DHR12R1; + } else { + base = (uint32_t)&DAC->DHR12R2; + } + + dma_nohal_deinit(dma_descr); + dma_nohal_init(dma_descr, DMA_MEMORY_TO_PERIPH | dma_mode | dma_align); + dma_nohal_start(dma_descr, (uint32_t)buf, base + dac_align, len); + + DAC->CR |= DAC_CR_EN1 << dac_channel; +} + /******************************************************************************/ // MicroPython bindings -typedef enum { - DAC_STATE_RESET, - DAC_STATE_WRITE_SINGLE, - DAC_STATE_BUILTIN_WAVEFORM, - DAC_STATE_DMA_WAVEFORM, // should be last enum since we use space beyond it -} pyb_dac_state_t; - typedef struct _pyb_dac_obj_t { mp_obj_base_t base; - uint32_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2 - const dma_descr_t *tx_dma_descr; - mp_hal_pin_obj_t pin; // pin_A4 or pin_A5 + uint8_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2 uint8_t bits; // 8 or 12 - uint8_t state; uint8_t outbuf_single; uint8_t outbuf_waveform; } pyb_dac_obj_t; +STATIC pyb_dac_obj_t pyb_dac_obj[2]; + +STATIC void pyb_dac_reconfigure(pyb_dac_obj_t *self, uint32_t cr, uint32_t outbuf, uint32_t value) { + bool restart = false; + const uint32_t cr_mask = DAC_CR_DMAEN1 | DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1 | DAC_CR_EN1; + if (((DAC->CR >> self->dac_channel) & cr_mask) != (cr | DAC_CR_EN1)) { + const dma_descr_t *tx_dma_descr; + if (self->dac_channel == DAC_CHANNEL_1) { + tx_dma_descr = &dma_DAC_1_TX; + } else { + tx_dma_descr = &dma_DAC_2_TX; + } + dma_nohal_deinit(tx_dma_descr); + dac_config_channel(self->dac_channel, cr, outbuf); + restart = true; + } + dac_set_value(self->dac_channel, DAC_ALIGN_12B_R, value); + if (restart) { + dac_start(self->dac_channel); + } +} + STATIC void pyb_dac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "DAC(%u, bits=%u)", @@ -170,7 +231,13 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // GPIO configuration - mp_hal_pin_config(self->pin, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_obj_t pin; + if (self->dac_channel == DAC_CHANNEL_1) { + pin = pin_A4; + } else { + pin = pin_A5; + } + mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); // DAC peripheral clock #if defined(STM32F4) || defined(STM32F7) @@ -183,20 +250,8 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp #error Unsupported Processor #endif - // stop anything already going on - __HAL_RCC_DMA1_CLK_ENABLE(); - DMA_HandleTypeDef DMA_Handle; - /* Get currently configured dma */ - dma_init_handle(&DMA_Handle, self->tx_dma_descr, DMA_MEMORY_TO_PERIPH, (void*)NULL); - // Need to deinit DMA first - DMA_Handle.State = HAL_DMA_STATE_READY; - HAL_DMA_DeInit(&DMA_Handle); - - HAL_DAC_Stop(&DAC_Handle, self->dac_channel); - if ((self->dac_channel == DAC_CHANNEL_1 && DAC_Handle.DMA_Handle1 != NULL) - || (self->dac_channel == DAC_CHANNEL_2 && DAC_Handle.DMA_Handle2 != NULL)) { - HAL_DAC_Stop_DMA(&DAC_Handle, self->dac_channel); - } + // Stop the DAC in case it was already running + DAC->CR &= ~(DAC_CR_EN1 << self->dac_channel); // set bit resolution if (args[0].u_int == 8 || args[0].u_int == 12) { @@ -218,9 +273,6 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp self->outbuf_waveform = DAC_OUTPUTBUFFER_DISABLE; } - // reset state of DAC - self->state = DAC_STATE_RESET; - return mp_const_none; } @@ -251,25 +303,25 @@ STATIC mp_obj_t pyb_dac_make_new(const mp_obj_type_t *type, size_t n_args, size_ } } - pyb_dac_obj_t *dac = m_new_obj(pyb_dac_obj_t); - dac->base.type = &pyb_dac_type; - + uint32_t dac_channel; if (dac_id == 1) { - dac->pin = pin_A4; - dac->dac_channel = DAC_CHANNEL_1; - dac->tx_dma_descr = &dma_DAC_1_TX; + dac_channel = DAC_CHANNEL_1; } else if (dac_id == 2) { - dac->pin = pin_A5; - dac->dac_channel = DAC_CHANNEL_2; - dac->tx_dma_descr = &dma_DAC_2_TX; + dac_channel = DAC_CHANNEL_2; } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "DAC(%d) doesn't exist", dac_id)); } - // configure the peripheral - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - pyb_dac_init_helper(dac, n_args - 1, args + 1, &kw_args); + pyb_dac_obj_t *dac = &pyb_dac_obj[dac_id - 1]; + dac->base.type = &pyb_dac_type; + dac->dac_channel = dac_channel; + + if (dac->bits == 0 || n_args > 1 || n_kw > 0) { + // configure the peripheral + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pyb_dac_init_helper(dac, n_args - 1, args + 1, &kw_args); + } // return object return MP_OBJ_FROM_PTR(dac); @@ -284,21 +336,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_init_obj, 1, pyb_dac_init); /// Turn off the DAC, enable other use of pin. STATIC mp_obj_t pyb_dac_deinit(mp_obj_t self_in) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->dac_channel == DAC_CHANNEL_1) { - DAC_Handle.Instance->CR &= ~DAC_CR_EN1; - #if defined(STM32H7) || defined(STM32L4) - DAC->MCR = (DAC->MCR & ~(7 << DAC_MCR_MODE1_Pos)) | 2 << DAC_MCR_MODE1_Pos; - #else - DAC_Handle.Instance->CR |= DAC_CR_BOFF1; - #endif - } else { - DAC_Handle.Instance->CR &= ~DAC_CR_EN2; - #if defined(STM32H7) || defined(STM32L4) - DAC->MCR = (DAC->MCR & ~(7 << DAC_MCR_MODE2_Pos)) | 2 << DAC_MCR_MODE2_Pos; - #else - DAC_Handle.Instance->CR |= DAC_CR_BOFF2; - #endif - } + dac_deinit(self->dac_channel); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_dac_deinit_obj, pyb_dac_deinit); @@ -313,19 +351,9 @@ STATIC mp_obj_t pyb_dac_noise(mp_obj_t self_in, mp_obj_t freq) { // set TIM6 to trigger the DAC at the given frequency TIM6_Config(mp_obj_get_int(freq)); - if (self->state != DAC_STATE_BUILTIN_WAVEFORM) { - // configure DAC to trigger via TIM6 - DAC_ChannelConfTypeDef config; - config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; - config.DAC_OutputBuffer = self->outbuf_waveform; - HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); - self->state = DAC_STATE_BUILTIN_WAVEFORM; - } - - // set noise wave generation - HAL_DACEx_NoiseWaveGenerate(&DAC_Handle, self->dac_channel, DAC_LFSRUNMASK_BITS10_0); - HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_12B_L, 0x7ff0); - HAL_DAC_Start(&DAC_Handle, self->dac_channel); + // Configure DAC in noise mode with trigger via TIM6 + uint32_t cr = DAC_LFSRUNMASK_BITS11_0 | DAC_CR_WAVE1_0 | DAC_TRIGGER_T6_TRGO; + pyb_dac_reconfigure(self, cr, self->outbuf_waveform, 0); return mp_const_none; } @@ -343,19 +371,9 @@ STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) { // set TIM6 to trigger the DAC at the given frequency TIM6_Config(mp_obj_get_int(freq)); - if (self->state != DAC_STATE_BUILTIN_WAVEFORM) { - // configure DAC to trigger via TIM6 - DAC_ChannelConfTypeDef config; - config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; - config.DAC_OutputBuffer = self->outbuf_waveform; - HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); - self->state = DAC_STATE_BUILTIN_WAVEFORM; - } - - // set triangle wave generation - HAL_DACEx_TriangleWaveGenerate(&DAC_Handle, self->dac_channel, DAC_TRIANGLEAMPLITUDE_1023); - HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_12B_R, 0x100); - HAL_DAC_Start(&DAC_Handle, self->dac_channel); + // Configure DAC in triangle mode with trigger via TIM6 + uint32_t cr = DAC_TRIANGLEAMPLITUDE_4095 | DAC_CR_WAVE1_1 | DAC_TRIGGER_T6_TRGO; + pyb_dac_reconfigure(self, cr, self->outbuf_waveform, 0); return mp_const_none; } @@ -367,20 +385,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_triangle_obj, pyb_dac_triangle); STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->state != DAC_STATE_WRITE_SINGLE) { - DAC_ChannelConfTypeDef config; - config.DAC_Trigger = DAC_TRIGGER_NONE; - config.DAC_OutputBuffer = self->outbuf_single; - HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); - self->state = DAC_STATE_WRITE_SINGLE; - } - // DAC output is always 12-bit at the hardware level, and we provide support // for multiple bit "resolutions" simply by shifting the input value. - HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_12B_R, - mp_obj_get_int(val) << (12 - self->bits)); - - HAL_DAC_Start(&DAC_Handle, self->dac_channel); + uint32_t cr = DAC_TRIGGER_NONE; + uint32_t value = mp_obj_get_int(val) << (12 - self->bits); + pyb_dac_reconfigure(self, cr, self->outbuf_single, value); return mp_const_none; } @@ -432,83 +441,24 @@ mp_obj_t pyb_dac_write_timed(size_t n_args, const mp_obj_t *pos_args, mp_map_t * dac_trigger = TIMx_Config(args[1].u_obj); } - __HAL_RCC_DMA1_CLK_ENABLE(); - - DMA_HandleTypeDef DMA_Handle; - /* Get currently configured dma */ - dma_init_handle(&DMA_Handle, self->tx_dma_descr, DMA_MEMORY_TO_PERIPH, (void*)NULL); - /* - DMA_Cmd(DMA_Handle->Instance, DISABLE); - while (DMA_GetCmdStatus(DMA_Handle->Instance) != DISABLE) { - } - - DAC_Cmd(self->dac_channel, DISABLE); - */ - - /* - // DAC channel configuration - DAC_InitTypeDef DAC_InitStructure; - DAC_InitStructure.DAC_Trigger = DAC_Trigger_T7_TRGO; - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1; // unused, but need to set it to a valid value - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; - DAC_Init(self->dac_channel, &DAC_InitStructure); - */ - - // Need to deinit DMA first - DMA_Handle.State = HAL_DMA_STATE_READY; - HAL_DMA_DeInit(&DMA_Handle); - - if (self->bits == 8) { - DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; - DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; - } else { - DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - } - DMA_Handle.Init.Mode = args[2].u_int; - HAL_DMA_Init(&DMA_Handle); + dac_config_channel(self->dac_channel, DAC_CR_DMAEN1 | dac_trigger, self->outbuf_waveform); + const dma_descr_t *tx_dma_descr; if (self->dac_channel == DAC_CHANNEL_1) { - __HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle); + tx_dma_descr = &dma_DAC_1_TX; } else { - __HAL_LINKDMA(&DAC_Handle, DMA_Handle2, DMA_Handle); - } - - DAC_Handle.Instance = DAC; - DAC_Handle.State = HAL_DAC_STATE_RESET; - HAL_DAC_Init(&DAC_Handle); - - if (self->state != DAC_STATE_DMA_WAVEFORM + dac_trigger) { - DAC_ChannelConfTypeDef config; - config.DAC_Trigger = dac_trigger; - config.DAC_OutputBuffer = self->outbuf_waveform; - HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); - self->state = DAC_STATE_DMA_WAVEFORM + dac_trigger; + tx_dma_descr = &dma_DAC_2_TX; } + uint32_t align; if (self->bits == 8) { - HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, - (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R); + align = DAC_ALIGN_8B_R; } else { - HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, - (uint32_t*)bufinfo.buf, bufinfo.len / 2, DAC_ALIGN_12B_R); + align = DAC_ALIGN_12B_R; + bufinfo.len /= 2; } - /* - // enable DMA stream - DMA_Cmd(DMA_Handle->Instance, ENABLE); - while (DMA_GetCmdStatus(DMA_Handle->Instance) == DISABLE) { - } - - // enable DAC channel - DAC_Cmd(self->dac_channel, ENABLE); - - // enable DMA for DAC channel - DAC_DMACmd(self->dac_channel, ENABLE); - */ - - //printf("DMA: %p %lu\n", bufinfo.buf, bufinfo.len); + dac_start_dma(self->dac_channel, tx_dma_descr, args[2].u_int, self->bits, align, bufinfo.len, bufinfo.buf); return mp_const_none; } diff --git a/ports/stm32/dac.h b/ports/stm32/dac.h index 1d8f0ab61e70c..fca36e019ea83 100644 --- a/ports/stm32/dac.h +++ b/ports/stm32/dac.h @@ -26,8 +26,6 @@ #ifndef MICROPY_INCLUDED_STM32_DAC_H #define MICROPY_INCLUDED_STM32_DAC_H -void dac_init(void); - extern const mp_obj_type_t pyb_dac_type; #endif // MICROPY_INCLUDED_STM32_DAC_H diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 3b8b74081c856..a4ddcc42f91d6 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 Damien P. George + * Copyright (c) 2015-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +29,7 @@ #include #include "py/obj.h" +#include "py/mphal.h" #include "systick.h" #include "dma.h" #include "irq.h" @@ -729,3 +730,100 @@ static void dma_idle_handler(uint32_t tick) { } } } + +#if defined(STM32F0) || defined(STM32L4) + +void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { + DMA_Channel_TypeDef *dma = descr->instance; + + // Enable the DMA peripheral + dma_enable_clock(descr->id); + + // Set main configuration register + dma->CCR = + descr->init->Priority // PL + | descr->init->MemInc // MINC + | descr->init->PeriphInc // PINC + | config // MSIZE | PSIZE | CIRC | DIR + ; + + // Select channel that the DMA stream uses + #if defined(STM32F0) + if (dma < DMA2_Channel1) { + __HAL_DMA1_REMAP(descr->sub_instance); + } else { + __HAL_DMA2_REMAP(descr->sub_instance); + } + #else + DMA_Request_TypeDef *dma_ctrl = (void*)(((uint32_t)dma & ~0xff) + (DMA1_CSELR_BASE - DMA1_BASE)); // DMA1_CSELR or DMA2_CSELR + uint32_t channel_number = (((uint32_t)dma & 0xff) - 0x08) / 20; // 0 through 6 + uint32_t channel_pos = channel_number * 4; + dma_ctrl->CSELR = (dma_ctrl->CSELR & ~(0xf << channel_pos)) | (descr->sub_instance << channel_pos); + #endif +} + +void dma_nohal_deinit(const dma_descr_t *descr) { + DMA_Channel_TypeDef *dma = descr->instance; + dma->CCR &= ~DMA_CCR_EN; + dma->CCR = 0; + dma->CNDTR = 0; + dma_deinit(descr); +} + +void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_addr, uint16_t len) { + DMA_Channel_TypeDef *dma = descr->instance; + dma->CNDTR = len; + dma->CPAR = dst_addr; + dma->CMAR = src_addr; + dma->CCR |= DMA_CCR_EN; +} + +#else + +void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { + DMA_Stream_TypeDef *dma = descr->instance; + + // Enable the DMA peripheral + dma_enable_clock(descr->id); + + // Set main configuration register + const DMA_InitTypeDef *init = descr->init; + dma->CR = + descr->sub_instance // CHSEL + | init->MemBurst // MBURST + | init->PeriphBurst // PBURST + | init->Priority // PL + | init->MemInc // MINC + | init->PeriphInc // PINC + | config // MSIZE | PSIZE | CIRC | DIR + ; + + // Set FIFO control register + dma->FCR = + init->FIFOMode // DMDIS + | init->FIFOThreshold // FTH + ; +} + +void dma_nohal_deinit(const dma_descr_t *descr) { + DMA_Stream_TypeDef *dma = descr->instance; + dma->CR &= ~DMA_SxCR_EN; + uint32_t t0 = mp_hal_ticks_ms(); + while ((dma->CR & DMA_SxCR_EN) && mp_hal_ticks_ms() - t0 < 100) { + } + dma->CR = 0; + dma->NDTR = 0; + dma->FCR = 0x21; + dma_deinit(descr); +} + +void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_addr, uint16_t len) { + DMA_Stream_TypeDef *dma = descr->instance; + dma->CR &= ~DMA_SxCR_DBM; + dma->NDTR = len; + dma->PAR = dst_addr; + dma->M0AR = src_addr; + dma->CR |= DMA_SxCR_EN; +} + +#endif diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 73cb9c32826a2..7b74a7399349d 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -86,4 +86,8 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 void dma_deinit(const dma_descr_t *dma_descr); void dma_invalidate_channel(const dma_descr_t *dma_descr); +void dma_nohal_init(const dma_descr_t *descr, uint32_t config); +void dma_nohal_deinit(const dma_descr_t *descr); +void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_addr, uint16_t len); + #endif // MICROPY_INCLUDED_STM32_DMA_H diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 8c2d7d529ae02..6fa6a6267f79e 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -721,10 +721,6 @@ void stm32_main(uint32_t reset_mode) { servo_init(); #endif - #if MICROPY_HW_ENABLE_DAC - dac_init(); - #endif - #if MICROPY_PY_NETWORK mod_network_init(); #endif From 56f6ceba7f6e86a47680660dbfe81a0a64682eaf Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 25 Apr 2019 13:24:32 +1000 Subject: [PATCH 0022/1299] tools/pyboard.py: Don't accumulate output data if data_consumer used. Prior to this patch, when a lot of data was output by a running script pyboard.py would try to capture all of this output into the "data" variable, which would gradually slow down pyboard.py to the point where it would have large CPU and memory usage (on the host) and potentially lose data. This patch fixes this problem by not accumulating the data in the case that the data is not needed, which is when "data_consumer" is used. --- tools/pyboard.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 42b077de2240e..d906235066be5 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -261,6 +261,9 @@ def close(self): self.serial.close() def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): + # if data_consumer is used then data is not accumulated and the ending must be 1 byte long + assert data_consumer is None or len(ending) == 1 + data = self.serial.read(min_num_bytes) if data_consumer: data_consumer(data) @@ -270,9 +273,11 @@ def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): break elif self.serial.inWaiting() > 0: new_data = self.serial.read(1) - data = data + new_data if data_consumer: data_consumer(new_data) + data = new_data + else: + data = data + new_data timeout_count = 0 else: timeout_count += 1 From f66c4cbfa6801e154e9f4bd54b8b89a44814af37 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 25 Apr 2019 17:56:13 +1000 Subject: [PATCH 0023/1299] stm32/usbdev: Make USB device descriptors at runtime rather than static. --- .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 402 +++++------------- 1 file changed, 101 insertions(+), 301 deletions(-) diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index a576796e27a6f..78ad72056abf7 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -30,18 +30,17 @@ #if MICROPY_HW_ENABLE_USB -#define MSC_TEMPLATE_CONFIG_DESC_SIZE (32) +#define HEAD_DESC_SIZE (9) +#define MSC_CLASS_DESC_SIZE (9 + 7 + 7) +#define CDC_CLASS_DESC_SIZE (8 + 58) +#define HID_CLASS_DESC_SIZE (9 + 9 + 7 + 7) + #define MSC_TEMPLATE_MSC_DESC_OFFSET (9) -#define CDC_TEMPLATE_CONFIG_DESC_SIZE (67) -#define CDC_MSC_TEMPLATE_CONFIG_DESC_SIZE (98) #define CDC_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC_MSC_TEMPLATE_CDC_DESC_OFFSET (40) -#define CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58)) #define CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8) #define CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8) -#define CDC_HID_TEMPLATE_CONFIG_DESC_SIZE (107) -#define CDC_HID_TEMPLATE_HID_DESC_OFFSET (9) #define CDC_HID_TEMPLATE_CDC_DESC_OFFSET (49) #define CDC_TEMPLATE_CDC_DESC_OFFSET (9) #define CDC_DESC_OFFSET_INTR_INTERVAL (34) @@ -126,68 +125,23 @@ __ALIGN_BEGIN static uint8_t USBD_CDC_MSC_HID_DeviceQualifierDesc[USB_LEN_DEV_QU }; #endif -// USB MSC device Configuration Descriptor -static const uint8_t msc_template_config_desc[MSC_TEMPLATE_CONFIG_DESC_SIZE] = { +// USB partial configuration descriptor +static const uint8_t head_desc_data[HEAD_DESC_SIZE] = { //-------------------------------------------------------------------------- // Configuration Descriptor 0x09, // bLength: Configuration Descriptor size USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration - LOBYTE(MSC_TEMPLATE_CONFIG_DESC_SIZE), // wTotalLength: no of returned bytes - HIBYTE(MSC_TEMPLATE_CONFIG_DESC_SIZE), - 0x01, // bNumInterfaces: 1 interfaces + 0x00, // wTotalLength -- to be filled in + 0x00, // wTotalLength -- to be filled in + 0x00, // bNumInterfaces -- to be filled in 0x01, // bConfigurationValue: Configuration value 0x00, // iConfiguration: Index of string descriptor describing the configuration CONFIG_DESC_ATTRIBUTES, // bmAttributes CONFIG_DESC_MAXPOWER, // bMaxPower - - //========================================================================== - // MSC only has 1 interface so doesn't need an IAD - - //-------------------------------------------------------------------------- - // Interface Descriptor - 0x09, // bLength: Interface Descriptor size - USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface descriptor - MSC_IFACE_NUM_WITH_CDC, // bInterfaceNumber: Number of Interface - 0x00, // bAlternateSetting: Alternate setting - 0x02, // bNumEndpoints - 0x08, // bInterfaceClass: MSC Class - 0x06, // bInterfaceSubClass : SCSI transparent - 0x50, // nInterfaceProtocol - 0x00, // iInterface: - - // Endpoint IN descriptor - 0x07, // bLength: Endpoint descriptor length - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type - MSC_IN_EP, // bEndpointAddress: IN, address 3 - 0x02, // bmAttributes: Bulk endpoint type - LOBYTE(MSC_FS_MAX_PACKET), // wMaxPacketSize - HIBYTE(MSC_FS_MAX_PACKET), - 0x00, // bInterval: ignore for Bulk transfer - - // Endpoint OUT descriptor - 0x07, // bLength: Endpoint descriptor length - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint descriptor type - MSC_OUT_EP, // bEndpointAddress: OUT, address 3 - 0x02, // bmAttributes: Bulk endpoint type - LOBYTE(MSC_FS_MAX_PACKET), // wMaxPacketSize - HIBYTE(MSC_FS_MAX_PACKET), - 0x00, // bInterval: ignore for Bulk transfer }; -// USB CDC MSC device Configuration Descriptor -static const uint8_t cdc_msc_template_config_desc[CDC_MSC_TEMPLATE_CONFIG_DESC_SIZE] = { - //-------------------------------------------------------------------------- - // Configuration Descriptor - 0x09, // bLength: Configuration Descriptor size - USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration - LOBYTE(CDC_MSC_TEMPLATE_CONFIG_DESC_SIZE), // wTotalLength: no of returned bytes - HIBYTE(CDC_MSC_TEMPLATE_CONFIG_DESC_SIZE), - 0x03, // bNumInterfaces: 3 interfaces - 0x01, // bConfigurationValue: Configuration value - 0x00, // iConfiguration: Index of string descriptor describing the configuration - CONFIG_DESC_ATTRIBUTES, // bmAttributes - CONFIG_DESC_MAXPOWER, // bMaxPower - +// USB MSC partial configuration descriptor +static const uint8_t msc_class_desc_data[MSC_CLASS_DESC_SIZE] = { //========================================================================== // MSC only has 1 interface so doesn't need an IAD @@ -220,12 +174,15 @@ static const uint8_t cdc_msc_template_config_desc[CDC_MSC_TEMPLATE_CONFIG_DESC_S LOBYTE(MSC_FS_MAX_PACKET), // wMaxPacketSize HIBYTE(MSC_FS_MAX_PACKET), 0x00, // bInterval: ignore for Bulk transfer +}; +// USB CDC partial configuration descriptor +static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { //========================================================================== // Interface Association for CDC VCP 0x08, // bLength: 8 bytes USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD - CDC_IFACE_NUM_WITH_MSC, // bFirstInterface: first interface for this association + 0x00, // bFirstInterface: first interface for this association -- to be filled in 0x02, // bInterfaceCount: nummber of interfaces for this association 0x02, // bFunctionClass: Communication Interface Class 0x02, // bFunctionSubClass: Abstract Control Model @@ -236,7 +193,7 @@ static const uint8_t cdc_msc_template_config_desc[CDC_MSC_TEMPLATE_CONFIG_DESC_S // Interface Descriptor 0x09, // bLength: Interface Descriptor size USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface - CDC_IFACE_NUM_WITH_MSC, // bInterfaceNumber: Number of Interface + 0x00, // bInterfaceNumber: Number of Interface -- to be filled in 0x00, // bAlternateSetting: Alternate setting 0x01, // bNumEndpoints: One endpoints used 0x02, // bInterfaceClass: Communication Interface Class @@ -256,7 +213,7 @@ static const uint8_t cdc_msc_template_config_desc[CDC_MSC_TEMPLATE_CONFIG_DESC_S 0x24, // bDescriptorType: CS_INTERFACE 0x01, // bDescriptorSubtype: Call Management Func Desc 0x00, // bmCapabilities: D0+D1 - CDC_IFACE_NUM_WITH_MSC + 1, // bDataInterface: 1 + 0x00, // bDataInterface -- to be filled in // ACM Functional Descriptor 0x04, // bFunctionLength @@ -268,10 +225,10 @@ static const uint8_t cdc_msc_template_config_desc[CDC_MSC_TEMPLATE_CONFIG_DESC_S 0x05, // bFunctionLength 0x24, // bDescriptorType: CS_INTERFACE 0x06, // bDescriptorSubtype: Union func desc - CDC_IFACE_NUM_WITH_MSC + 0, // bMasterInterface: Communication class interface - CDC_IFACE_NUM_WITH_MSC + 1, // bSlaveInterface0: Data Class Interface + 0x00, // bMasterInterface: Communication class interface -- to be filled in + 0x00, // bSlaveInterface0: Data Class Interface -- to be filled in - // Endpoint 2 Descriptor + // Endpoint CMD Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint CDC_CMD_EP, // bEndpointAddress @@ -284,7 +241,7 @@ static const uint8_t cdc_msc_template_config_desc[CDC_MSC_TEMPLATE_CONFIG_DESC_S // Data class interface descriptor 0x09, // bLength: Endpoint Descriptor size USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface - CDC_IFACE_NUM_WITH_MSC + 1, // bInterfaceNumber: Number of Interface + 0x00, // bInterfaceNumber: Number of Interface -- to be filled in 0x00, // bAlternateSetting: Alternate setting 0x02, // bNumEndpoints: Two endpoints used 0x0A, // bInterfaceClass: CDC @@ -311,20 +268,8 @@ static const uint8_t cdc_msc_template_config_desc[CDC_MSC_TEMPLATE_CONFIG_DESC_S 0x00, // bInterval: ignore for Bulk transfer }; -// USB CDC HID device Configuration Descriptor -static const uint8_t cdc_hid_template_config_desc[CDC_HID_TEMPLATE_CONFIG_DESC_SIZE] = { - //-------------------------------------------------------------------------- - // Configuration Descriptor - 0x09, // bLength: Configuration Descriptor size - USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration - LOBYTE(CDC_HID_TEMPLATE_CONFIG_DESC_SIZE), // wTotalLength: no of returned bytes - HIBYTE(CDC_HID_TEMPLATE_CONFIG_DESC_SIZE), - 0x03, // bNumInterfaces: 3 interfaces - 0x01, // bConfigurationValue: Configuration value - 0x00, // iConfiguration: Index of string descriptor describing the configuration - CONFIG_DESC_ATTRIBUTES, // bmAttributes - CONFIG_DESC_MAXPOWER, // bMaxPower - +// USB HID partial configuration descriptor +static const uint8_t hid_class_desc_data[HID_CLASS_DESC_SIZE] = { //========================================================================== // HID only has 1 interface so doesn't need an IAD @@ -368,187 +313,6 @@ static const uint8_t cdc_hid_template_config_desc[CDC_HID_TEMPLATE_CONFIG_DESC_S LOBYTE(USBD_HID_MOUSE_MAX_PACKET), // wMaxPacketSize HIBYTE(USBD_HID_MOUSE_MAX_PACKET), 0x08, // bInterval: Polling interval - - //========================================================================== - // Interface Association for CDC VCP - 0x08, // bLength: 8 bytes - USB_DESC_TYPE_ASSOCIATION, // bDescriptorType: IAD - CDC_IFACE_NUM_WITH_HID, // bFirstInterface: first interface for this association - 0x02, // bInterfaceCount: nummber of interfaces for this association - 0x02, // bFunctionClass: Communication Interface Class - 0x02, // bFunctionSubClass: Abstract Control Model - 0x01, // bFunctionProtocol: Common AT commands - 0x00, // iFunction: index of string for this function - - //-------------------------------------------------------------------------- - // Interface Descriptor - 0x09, // bLength: Interface Descriptor size - USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface - CDC_IFACE_NUM_WITH_HID, // bInterfaceNumber: Number of Interface - 0x00, // bAlternateSetting: Alternate setting - 0x01, // bNumEndpoints: One endpoints used - 0x02, // bInterfaceClass: Communication Interface Class - 0x02, // bInterfaceSubClass: Abstract Control Model - 0x01, // bInterfaceProtocol: Common AT commands - 0x00, // iInterface: - - // Header Functional Descriptor - 0x05, // bLength: Endpoint Descriptor size - 0x24, // bDescriptorType: CS_INTERFACE - 0x00, // bDescriptorSubtype: Header Func Desc - 0x10, // bcdCDC: spec release number - 0x01, // ? - - // Call Management Functional Descriptor - 0x05, // bFunctionLength - 0x24, // bDescriptorType: CS_INTERFACE - 0x01, // bDescriptorSubtype: Call Management Func Desc - 0x00, // bmCapabilities: D0+D1 - CDC_IFACE_NUM_WITH_HID + 1, // bDataInterface: 1 - - // ACM Functional Descriptor - 0x04, // bFunctionLength - 0x24, // bDescriptorType: CS_INTERFACE - 0x02, // bDescriptorSubtype: Abstract Control Management desc - 0x02, // bmCapabilities - - // Union Functional Descriptor - 0x05, // bFunctionLength - 0x24, // bDescriptorType: CS_INTERFACE - 0x06, // bDescriptorSubtype: Union func desc - CDC_IFACE_NUM_WITH_HID + 0, // bMasterInterface: Communication class interface - CDC_IFACE_NUM_WITH_HID + 1, // bSlaveInterface0: Data Class Interface - - // Endpoint 2 Descriptor - 0x07, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_CMD_EP, // bEndpointAddress - 0x03, // bmAttributes: Interrupt - LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize: - HIBYTE(CDC_CMD_PACKET_SIZE), - 0x20, // bInterval: polling interval in frames of 1ms - - //-------------------------------------------------------------------------- - // Data class interface descriptor - 0x09, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_INTERFACE, // bDescriptorType: interface - CDC_IFACE_NUM_WITH_HID + 1, // bInterfaceNumber: Number of Interface - 0x00, // bAlternateSetting: Alternate setting - 0x02, // bNumEndpoints: Two endpoints used - 0x0A, // bInterfaceClass: CDC - 0x00, // bInterfaceSubClass: ? - 0x00, // bInterfaceProtocol: ? - 0x00, // iInterface: - - // Endpoint OUT Descriptor - 0x07, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_OUT_EP, // bEndpointAddress - 0x02, // bmAttributes: Bulk - LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: - HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), - 0x00, // bInterval: ignore for Bulk transfer - - // Endpoint IN Descriptor - 0x07, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_IN_EP, // bEndpointAddress - 0x02, // bmAttributes: Bulk - LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: - HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), - 0x00, // bInterval: ignore for Bulk transfer -}; - -static const uint8_t cdc_template_config_desc[CDC_TEMPLATE_CONFIG_DESC_SIZE] = { - //-------------------------------------------------------------------------- - // Configuration Descriptor - 0x09, // bLength: Configuration Descriptor size - USB_DESC_TYPE_CONFIGURATION, // bDescriptorType: Configuration - LOBYTE(CDC_TEMPLATE_CONFIG_DESC_SIZE), // wTotalLength:no of returned bytes - HIBYTE(CDC_TEMPLATE_CONFIG_DESC_SIZE), - 0x02, // bNumInterfaces: 2 interface - 0x01, // bConfigurationValue: Configuration value - 0x00, // iConfiguration: Index of string descriptor describing the configuration - CONFIG_DESC_ATTRIBUTES, // bmAttributes - CONFIG_DESC_MAXPOWER, // bMaxPower - - //-------------------------------------------------------------------------- - // Interface Descriptor - 0x09, // bLength: Interface Descriptor size - USB_DESC_TYPE_INTERFACE, // bDescriptorType: Interface - CDC_IFACE_NUM_ALONE, // bInterfaceNumber: Number of Interface - 0x00, // bAlternateSetting: Alternate setting - 0x01, // bNumEndpoints: One endpoints used - 0x02, // bInterfaceClass: Communication Interface Class - 0x02, // bInterfaceSubClass: Abstract Control Model - 0x01, // bInterfaceProtocol: Common AT commands - 0x00, // iInterface: - - // Header Functional Descriptor - 0x05, // bLength: Endpoint Descriptor size - 0x24, // bDescriptorType: CS_INTERFACE - 0x00, // bDescriptorSubtype: Header Func Desc - 0x10, // bcdCDC: spec release number - 0x01, // ? - - // Call Management Functional Descriptor - 0x05, // bFunctionLength - 0x24, // bDescriptorType: CS_INTERFACE - 0x01, // bDescriptorSubtype: Call Management Func Desc - 0x00, // bmCapabilities: D0+D1 - CDC_IFACE_NUM_ALONE + 1, // bDataInterface: 1 - - // ACM Functional Descriptor - 0x04, // bFunctionLength - 0x24, // bDescriptorType: CS_INTERFACE - 0x02, // bDescriptorSubtype: Abstract Control Management desc - 0x02, // bmCapabilities - - // Union Functional Descriptor - 0x05, // bFunctionLength - 0x24, // bDescriptorType: CS_INTERFACE - 0x06, // bDescriptorSubtype: Union func desc - CDC_IFACE_NUM_ALONE + 0, // bMasterInterface: Communication class interface - CDC_IFACE_NUM_ALONE + 1, // bSlaveInterface0: Data Class Interface - - // Endpoint 2 Descriptor - 0x07, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_CMD_EP, // bEndpointAddress - 0x03, // bmAttributes: Interrupt - LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize: - HIBYTE(CDC_CMD_PACKET_SIZE), - 0x20, // bInterval: polling interval in frames of 1ms - - //-------------------------------------------------------------------------- - // Data class interface descriptor - 0x09, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_INTERFACE, // bDescriptorType: - CDC_IFACE_NUM_ALONE + 1, // bInterfaceNumber: Number of Interface - 0x00, // bAlternateSetting: Alternate setting - 0x02, // bNumEndpoints: Two endpoints used - 0x0a, // bInterfaceClass: CDC - 0x00, // bInterfaceSubClass: ? - 0x00, // bInterfaceProtocol: ? - 0x00, // iInterface: - - // Endpoint OUT Descriptor - 0x07, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_OUT_EP, // bEndpointAddress - 0x02, // bmAttributes: Bulk - LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: - HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), - 0x00, // bInterval: ignore for Bulk transfer - - // Endpoint IN Descriptor - 0x07, // bLength: Endpoint Descriptor size - USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_IN_EP, // bEndpointAddress - 0x02, // bmAttributes: Bulk - LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: - HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), - 0x00 // bInterval: ignore for Bulk transfer }; __ALIGN_BEGIN const uint8_t USBD_HID_MOUSE_ReportDesc[USBD_HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END = { @@ -628,6 +392,61 @@ __ALIGN_BEGIN const uint8_t USBD_HID_KEYBOARD_ReportDesc[USBD_HID_KEYBOARD_REPOR 0xC0 // End Collection }; +static void make_head_desc(uint8_t *dest, uint16_t len, uint8_t num_itf) { + memcpy(dest, head_desc_data, sizeof(head_desc_data)); + dest[2] = LOBYTE(len); // wTotalLength + dest[3] = HIBYTE(len); + dest[4] = num_itf; // bNumInterfaces +} + +static size_t make_msc_desc(uint8_t *dest) { + memcpy(dest, msc_class_desc_data, sizeof(msc_class_desc_data)); + return sizeof(msc_class_desc_data); +} + +static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) { + if (need_iad) { + memcpy(dest, cdc_class_desc_data, sizeof(cdc_class_desc_data)); + dest[2] = iface_num; // bFirstInterface + dest += 8; + } else { + memcpy(dest, cdc_class_desc_data + 8, sizeof(cdc_class_desc_data) - 8); + } + dest[2] = iface_num; // bInterfaceNumber, main class + dest[18] = iface_num + 1; // bDataInterface + dest[26] = iface_num + 0; // bMasterInterface + dest[27] = iface_num + 1; // bSlaveInterface + dest[37] = iface_num + 1; // bInterfaceNumber, data class + return need_iad ? 8 + 58 : 58; +} + +#if MICROPY_HW_USB_ENABLE_CDC2 +static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, uint8_t cmd_ep, uint8_t out_ep, uint8_t in_ep) { + size_t n = make_cdc_desc(dest, need_iad, iface_num); + if (need_iad) { + dest += 8; + } + dest[30] = cmd_ep; // bEndpointAddress, main class CMD + dest[46] = out_ep; // bEndpointAddress, data class OUT + dest[53] = in_ep; // bEndpointAddress, data class IN + return n; +} +#endif + +static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info) { + memcpy(dest, hid_class_desc_data, sizeof(hid_class_desc_data)); + dest[HID_DESC_OFFSET_SUBCLASS] = hid_info->subclass; + dest[HID_DESC_OFFSET_PROTOCOL] = hid_info->protocol; + dest[HID_DESC_OFFSET_REPORT_DESC_LEN] = hid_info->report_desc_len; + dest[HID_DESC_OFFSET_MAX_PACKET_LO] = hid_info->max_packet_len; + dest[HID_DESC_OFFSET_MAX_PACKET_HI] = 0; + dest[HID_DESC_OFFSET_POLLING_INTERVAL] = hid_info->polling_interval; + dest[HID_DESC_OFFSET_MAX_PACKET_OUT_LO] = hid_info->max_packet_len; + dest[HID_DESC_OFFSET_MAX_PACKET_OUT_HI] = 0; + dest[HID_DESC_OFFSET_POLLING_INTERVAL_OUT] = hid_info->polling_interval; + return sizeof(hid_class_desc_data); +} + // return the saved usb mode uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd) { return usbd->usbd_mode; @@ -638,57 +457,50 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode usbd->usbd_mode = mode; // construct config desc + size_t n = HEAD_DESC_SIZE; + uint8_t *d = usbd->usbd_config_desc; + uint8_t num_itf = 0; switch (usbd->usbd_mode) { case USBD_MODE_MSC: - usbd->usbd_config_desc_size = sizeof(msc_template_config_desc); - memcpy(usbd->usbd_config_desc, msc_template_config_desc, sizeof(msc_template_config_desc)); + n += make_msc_desc(d + n); + num_itf = 1; break; case USBD_MODE_CDC_MSC: - usbd->usbd_config_desc_size = sizeof(cdc_msc_template_config_desc); - memcpy(usbd->usbd_config_desc, cdc_msc_template_config_desc, sizeof(cdc_msc_template_config_desc)); + n += make_msc_desc(d + n); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC; + num_itf = 3; break; #if MICROPY_HW_USB_ENABLE_CDC2 case USBD_MODE_CDC2_MSC: { - usbd->usbd_config_desc_size = CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE; - uint8_t *d = usbd->usbd_config_desc; - memcpy(d, cdc_msc_template_config_desc, sizeof(cdc_msc_template_config_desc)); - d[2] = LOBYTE(CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE); // wTotalLength - d[3] = HIBYTE(CDC2_MSC_TEMPLATE_CONFIG_DESC_SIZE); - d[4] = 5; // bNumInterfaces - memcpy(d + 9 + 23 + (8 + 58), d + 9 + 23, 8 + 58); - d += 9 + 23 + (8 + 58); - d[2] = CDC2_IFACE_NUM_WITH_MSC; // bFirstInterface - d[10] = CDC2_IFACE_NUM_WITH_MSC; // bInterfaceNumber - d[26] = CDC2_IFACE_NUM_WITH_MSC + 1; // bDataInterface - d[34] = CDC2_IFACE_NUM_WITH_MSC + 0; // bMasterInterface - d[35] = CDC2_IFACE_NUM_WITH_MSC + 1; // bSlaveInterface - d[38] = CDC2_CMD_EP; // bEndpointAddress - d[45] = CDC2_IFACE_NUM_WITH_MSC + 1; // bInterfaceNumber - d[54] = CDC2_OUT_EP; // bEndpointAddress - d[61] = CDC2_IN_EP; // bEndpointAddress + n += make_msc_desc(d + n); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP); usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_MSC; + num_itf = 5; break; } #endif case USBD_MODE_CDC_HID: - usbd->usbd_config_desc_size = sizeof(cdc_hid_template_config_desc); - memcpy(usbd->usbd_config_desc, cdc_hid_template_config_desc, sizeof(cdc_hid_template_config_desc)); + usbd->hid->desc = d + n; + n += make_hid_desc(d + n, hid_info); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID); usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_HID; usbd->hid->in_ep = HID_IN_EP_WITH_CDC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC; - usbd->hid->desc = usbd->usbd_config_desc + CDC_HID_TEMPLATE_HID_DESC_OFFSET; + usbd->hid->report_desc = hid_info->report_desc; + num_itf = 3; break; case USBD_MODE_CDC: - usbd->usbd_config_desc_size = sizeof(cdc_template_config_desc); - memcpy(usbd->usbd_config_desc, cdc_template_config_desc, sizeof(cdc_template_config_desc)); + n += make_cdc_desc(d + n, 0, CDC_IFACE_NUM_ALONE); usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE; + num_itf = 2; break; /* @@ -705,6 +517,9 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode return -1; } + make_head_desc(d, n, num_itf); + usbd->usbd_config_desc_size = n; + if (usbd->usbd_mode & USBD_MODE_CDC) { usbd->cdc->in_ep = CDC_IN_EP; usbd->cdc->out_ep = CDC_OUT_EP; @@ -717,21 +532,6 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode } #endif - // configure the HID descriptor, if needed - if (usbd->usbd_mode & USBD_MODE_HID) { - uint8_t *hid_desc = usbd->hid->desc; - hid_desc[HID_DESC_OFFSET_SUBCLASS] = hid_info->subclass; - hid_desc[HID_DESC_OFFSET_PROTOCOL] = hid_info->protocol; - hid_desc[HID_DESC_OFFSET_REPORT_DESC_LEN] = hid_info->report_desc_len; - hid_desc[HID_DESC_OFFSET_MAX_PACKET_LO] = hid_info->max_packet_len; - hid_desc[HID_DESC_OFFSET_MAX_PACKET_HI] = 0; - hid_desc[HID_DESC_OFFSET_POLLING_INTERVAL] = hid_info->polling_interval; - hid_desc[HID_DESC_OFFSET_MAX_PACKET_OUT_LO] = hid_info->max_packet_len; - hid_desc[HID_DESC_OFFSET_MAX_PACKET_OUT_HI] = 0; - hid_desc[HID_DESC_OFFSET_POLLING_INTERVAL_OUT] = hid_info->polling_interval; - usbd->hid->report_desc = hid_info->report_desc; - } - return 0; } From 775ffdcc3b85178ac128f774a5a8f992fd637dca Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 26 Apr 2019 14:47:31 +1000 Subject: [PATCH 0024/1299] extmod/machine_signal: Fix fault when no args are passed to Signal(). --- extmod/machine_signal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c index c494490b60150..8204ef174a23c 100644 --- a/extmod/machine_signal.c +++ b/extmod/machine_signal.c @@ -43,13 +43,13 @@ typedef struct _machine_signal_t { } machine_signal_t; STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_obj_t pin = args[0]; + mp_obj_t pin; bool invert = false; #if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW) mp_pin_p_t *pin_p = NULL; - if (mp_obj_is_obj(pin)) { + if (n_args > 0 && mp_obj_is_obj(args[0])) { mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); pin_p = (mp_pin_p_t*)pin_base->type->protocol; } @@ -96,6 +96,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t // Otherwise there should be 1 or 2 args { if (n_args == 1) { + pin = args[0]; if (n_kw == 0) { } else if (n_kw == 1 && args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) { invert = mp_obj_is_true(args[2]); From 06a532c227c2f37fc190deb84970fdfeaaf37d6a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 26 Apr 2019 15:21:09 +1000 Subject: [PATCH 0025/1299] lib/utils/pyexec: Add pyexec_file_if_exists() helper function. It will only execute the script if it can be stat'd and is a file. --- lib/utils/pyexec.c | 8 ++++++++ lib/utils/pyexec.h | 1 + 2 files changed, 9 insertions(+) diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index f4e6856e506fa..946a97a00a395 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -541,6 +541,14 @@ int pyexec_file(const char *filename) { return parse_compile_execute(filename, MP_PARSE_FILE_INPUT, EXEC_FLAG_SOURCE_IS_FILENAME); } +int pyexec_file_if_exists(const char *filename) { + mp_import_stat_t stat = mp_import_stat(filename); + if (stat != MP_IMPORT_STAT_FILE) { + return 1; // success (no file is the same as an empty file executing without fail) + } + return pyexec_file(filename); +} + #if MICROPY_MODULE_FROZEN int pyexec_frozen_module(const char *name) { void *frozen_data; diff --git a/lib/utils/pyexec.h b/lib/utils/pyexec.h index a0d0b52b16146..9eb490be543fd 100644 --- a/lib/utils/pyexec.h +++ b/lib/utils/pyexec.h @@ -46,6 +46,7 @@ extern int pyexec_system_exit; int pyexec_raw_repl(void); int pyexec_friendly_repl(void); int pyexec_file(const char *filename); +int pyexec_file_if_exists(const char *filename); int pyexec_frozen_module(const char *name); void pyexec_event_repl_init(void); int pyexec_event_repl_process_char(int c); From 0646e607b537b43901db53c743ec2011a375f5e2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 26 Apr 2019 15:22:14 +1000 Subject: [PATCH 0026/1299] ports: Convert to use pyexec_file_if_exists() to execute boot/main.py. The stm32 and nrf ports already had the behaviour that they would first check if the script exists before executing it, and this patch makes all other ports work the same way. This helps when developing apps because it's hard to tell (when unconditionally trying to execute the scripts) if the resulting OSError at boot up comes from missing boot.py or main.py, or from some other error. And it's not really an error if these scripts don't exist. --- ports/cc3200/mptask.c | 4 ++-- ports/esp32/main.c | 4 ++-- ports/esp8266/main.c | 4 ++-- ports/nrf/main.c | 8 ++------ ports/stm32/main.c | 30 ++++++++++++------------------ ports/teensy/main.c | 4 ++-- 6 files changed, 22 insertions(+), 32 deletions(-) diff --git a/ports/cc3200/mptask.c b/ports/cc3200/mptask.c index 9d75f4678eb11..d35338be18c9a 100644 --- a/ports/cc3200/mptask.c +++ b/ports/cc3200/mptask.c @@ -180,7 +180,7 @@ void TASK_MicroPython (void *pvParameters) { if (!safeboot) { // run boot.py - int ret = pyexec_file("boot.py"); + int ret = pyexec_file_if_exists("boot.py"); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } @@ -205,7 +205,7 @@ void TASK_MicroPython (void *pvParameters) { } else { main_py = mp_obj_str_get_str(MP_STATE_PORT(machine_config_main)); } - int ret = pyexec_file(main_py); + int ret = pyexec_file_if_exists(main_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; } diff --git a/ports/esp32/main.c b/ports/esp32/main.c index 188fb5e70dd34..d4f79646f6c89 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -111,9 +111,9 @@ void mp_task(void *pvParameter) { // run boot-up scripts pyexec_frozen_module("_boot.py"); - pyexec_file("boot.py"); + pyexec_file_if_exists("boot.py"); if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { - pyexec_file("main.py"); + pyexec_file_if_exists("main.py"); } for (;;) { diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c index 67157ce18c563..3465e0446e4a3 100644 --- a/ports/esp8266/main.c +++ b/ports/esp8266/main.c @@ -77,9 +77,9 @@ STATIC void mp_reset(void) { #if MICROPY_MODULE_FROZEN pyexec_frozen_module("_boot.py"); - pyexec_file("boot.py"); + pyexec_file_if_exists("boot.py"); if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { - pyexec_file("main.py"); + pyexec_file_if_exists("main.py"); } #endif } diff --git a/ports/nrf/main.c b/ports/nrf/main.c index b9c29e7538d8c..e1ffce9385a20 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -227,12 +227,8 @@ pin_init0(); #if MICROPY_VFS || MICROPY_MBFS // run boot.py and main.py if they exist. - if (mp_import_stat("boot.py") == MP_IMPORT_STAT_FILE) { - pyexec_file("boot.py"); - } - if (mp_import_stat("main.py") == MP_IMPORT_STAT_FILE) { - pyexec_file("main.py"); - } + pyexec_file_if_exists("boot.py"); + pyexec_file_if_exists("main.py"); #endif for (;;) { diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 6fa6a6267f79e..0bdbbd481d452 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -678,15 +678,12 @@ void stm32_main(uint32_t reset_mode) { // TODO perhaps have pyb.reboot([bootpy]) function to soft-reboot and execute custom boot.py if (reset_mode == 1 || reset_mode == 3) { const char *boot_py = "boot.py"; - mp_import_stat_t stat = mp_import_stat(boot_py); - if (stat == MP_IMPORT_STAT_FILE) { - int ret = pyexec_file(boot_py); - if (ret & PYEXEC_FORCED_EXIT) { - goto soft_reset_exit; - } - if (!ret) { - flash_error(4); - } + int ret = pyexec_file_if_exists(boot_py); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + if (!ret) { + flash_error(4); } } @@ -735,15 +732,12 @@ void stm32_main(uint32_t reset_mode) { } else { main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main)); } - mp_import_stat_t stat = mp_import_stat(main_py); - if (stat == MP_IMPORT_STAT_FILE) { - int ret = pyexec_file(main_py); - if (ret & PYEXEC_FORCED_EXIT) { - goto soft_reset_exit; - } - if (!ret) { - flash_error(3); - } + int ret = pyexec_file_if_exists(main_py); + if (ret & PYEXEC_FORCED_EXIT) { + goto soft_reset_exit; + } + if (!ret) { + flash_error(3); } } diff --git a/ports/teensy/main.c b/ports/teensy/main.c index ad98a43644009..1f529f589c364 100644 --- a/ports/teensy/main.c +++ b/ports/teensy/main.c @@ -302,7 +302,7 @@ int main(void) { #if MICROPY_MODULE_FROZEN pyexec_frozen_module("boot.py"); #else - if (!pyexec_file("/boot.py")) { + if (!pyexec_file_if_exists("/boot.py")) { flash_error(4); } #endif @@ -322,7 +322,7 @@ int main(void) { } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main)); } - if (!pyexec_file(vstr_null_terminated_str(vstr))) { + if (!pyexec_file_if_exists(vstr_null_terminated_str(vstr))) { flash_error(3); } vstr_free(vstr); From 70a28e3ad9a251e77f0fa2da643f014044035a36 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Fri, 26 Apr 2019 16:31:49 +1000 Subject: [PATCH 0027/1299] stm32/usb: Add USB device mode for VCP+VCP without MSC. Selectable via pyb.usb_mode('VCP+VCP'). --- ports/stm32/usb.c | 5 +++++ ports/stm32/usb.h | 1 + ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 13 +++++++++++++ 3 files changed, 19 insertions(+) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index ce2a828598d4a..e81225e60577a 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -306,6 +306,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * } mode = USBD_MODE_CDC_MSC; #if MICROPY_HW_USB_ENABLE_CDC2 + } else if (strcmp(mode_str, "VCP+VCP") == 0) { + if (args[2].u_int == -1) { + pid = USBD_PID_CDC2; + } + mode = USBD_MODE_CDC2; } else if (strcmp(mode_str, "VCP+VCP+MSC") == 0) { if (args[2].u_int == -1) { pid = USBD_PID_CDC2_MSC; diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 2a3861f210c14..3d57bf9129cda 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -37,6 +37,7 @@ #define USBD_PID_CDC (0x9802) #define USBD_PID_MSC (0x9803) #define USBD_PID_CDC2_MSC (0x9804) +#define USBD_PID_CDC2 (0x9805) typedef enum { PYB_USB_STORAGE_MEDIUM_NONE = 0, diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 78ad72056abf7..47436a4b63497 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -62,6 +62,7 @@ #define CDC_IFACE_NUM_ALONE (0) #define CDC_IFACE_NUM_WITH_MSC (1) +#define CDC2_IFACE_NUM_WITH_CDC (2) #define CDC2_IFACE_NUM_WITH_MSC (3) #define CDC_IFACE_NUM_WITH_HID (1) #define MSC_IFACE_NUM_WITH_CDC (0) @@ -474,6 +475,18 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode break; #if MICROPY_HW_USB_ENABLE_CDC2 + case USBD_MODE_CDC2: { + // Ensure the first interface is also enabled + usbd->usbd_mode |= USBD_MODE_CDC; + + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE); + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP); + usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE; + usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_CDC; + num_itf = 4; + break; + } + case USBD_MODE_CDC2_MSC: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); From ca39ea7cef802497834aa2a0afa0ef8cae9ab800 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 28 Apr 2019 22:12:17 +1000 Subject: [PATCH 0028/1299] tests: Skip tests needing machine module if (u)machine doesn't exist. --- tests/basics/subclass_native_call.py | 10 +++++----- tests/extmod/machine_pinbase.py | 10 +++++----- tests/extmod/machine_pulse.py | 10 +++++----- tests/extmod/machine_signal.py | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/basics/subclass_native_call.py b/tests/basics/subclass_native_call.py index c645575225989..969f0a415ea15 100644 --- a/tests/basics/subclass_native_call.py +++ b/tests/basics/subclass_native_call.py @@ -4,13 +4,13 @@ # and is callable (has call). The only one available is machine.Signal, which # in turns needs PinBase. try: - import umachine as machine -except ImportError: - import machine -try: + try: + import umachine as machine + except ImportError: + import machine machine.PinBase machine.Signal -except AttributeError: +except: print("SKIP") raise SystemExit diff --git a/tests/extmod/machine_pinbase.py b/tests/extmod/machine_pinbase.py index e91775504d59a..45aa4d8b5b0b3 100644 --- a/tests/extmod/machine_pinbase.py +++ b/tests/extmod/machine_pinbase.py @@ -1,10 +1,10 @@ try: - import umachine as machine -except ImportError: - import machine -try: + try: + import umachine as machine + except ImportError: + import machine machine.PinBase -except AttributeError: +except: print("SKIP") raise SystemExit diff --git a/tests/extmod/machine_pulse.py b/tests/extmod/machine_pulse.py index d525974e0c2a9..458fe09a1113a 100644 --- a/tests/extmod/machine_pulse.py +++ b/tests/extmod/machine_pulse.py @@ -1,11 +1,11 @@ try: - import umachine as machine -except ImportError: - import machine -try: + try: + import umachine as machine + except ImportError: + import machine machine.PinBase machine.time_pulse_us -except AttributeError: +except: print("SKIP") raise SystemExit diff --git a/tests/extmod/machine_signal.py b/tests/extmod/machine_signal.py index 53f4f5890c3dd..dcc0de1a5d30c 100644 --- a/tests/extmod/machine_signal.py +++ b/tests/extmod/machine_signal.py @@ -1,13 +1,13 @@ # test machine.Signal class try: - import umachine as machine -except ImportError: - import machine -try: + try: + import umachine as machine + except ImportError: + import machine machine.PinBase machine.Signal -except AttributeError: +except: print("SKIP") raise SystemExit From bd0bacb637fb11556e76cbd929ed833dcd3abe97 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 28 Apr 2019 22:14:28 +1000 Subject: [PATCH 0029/1299] javascript/library: Use Buffer.alloc() since new Buffer() is deprecated. --- ports/javascript/library.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/javascript/library.js b/ports/javascript/library.js index ed58167d5d905..85fa3e2edd1be 100644 --- a/ports/javascript/library.js +++ b/ports/javascript/library.js @@ -48,7 +48,7 @@ mergeInto(LibraryManager.library, { var mp_interrupt_char = Module.ccall('mp_hal_get_interrupt_char', 'number', ['number'], ['null']); var fs = require('fs'); - var buf = new Buffer(1); + var buf = Buffer.alloc(1); try { var n = fs.readSync(process.stdin.fd, buf, 0, 1); if (n > 0) { From 93f5f802165c3b8ab01a0393409cbd1c352596c8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 28 Apr 2019 22:16:27 +1000 Subject: [PATCH 0030/1299] javascript: Pass (error) exit value out from script to process caller. --- ports/javascript/main.c | 19 +++++++++++++++---- ports/javascript/wrapper.js | 6 +++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ports/javascript/main.c b/ports/javascript/main.c index 65bae98b44d89..f8ef0e7c559b9 100644 --- a/ports/javascript/main.c +++ b/ports/javascript/main.c @@ -39,7 +39,8 @@ #include "library.h" #if MICROPY_ENABLE_COMPILER -void do_str(const char *src, mp_parse_input_kind_t input_kind) { +int do_str(const char *src, mp_parse_input_kind_t input_kind) { + int ret = 0; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); @@ -51,18 +52,28 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) { } else { // uncaught exception if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) { - // at the moment, the value of SystemExit is unused + mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + if (exit_val != mp_const_none) { + mp_int_t int_val; + if (mp_obj_get_int_maybe(exit_val, &int_val)) { + ret = int_val & 255; + } else { + ret = 1; + } + } } else { mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); + ret = 1; } } + return ret; } #endif static char *stack_top; -void mp_js_do_str(const char *code) { - do_str(code, MP_PARSE_FILE_INPUT); +int mp_js_do_str(const char *code) { + return do_str(code, MP_PARSE_FILE_INPUT); } int mp_js_process_char(int c) { diff --git a/ports/javascript/wrapper.js b/ports/javascript/wrapper.js index 84ad2ae3a7729..ae0f24e7e46d1 100644 --- a/ports/javascript/wrapper.js +++ b/ports/javascript/wrapper.js @@ -29,7 +29,7 @@ var Module = {}; var mainProgram = function() { mp_js_init = Module.cwrap('mp_js_init', 'null', ['number']); - mp_js_do_str = Module.cwrap('mp_js_do_str', 'null', ['string']); + mp_js_do_str = Module.cwrap('mp_js_do_str', 'number', ['string']); mp_js_init_repl = Module.cwrap('mp_js_init_repl', 'null', ['null']); mp_js_process_char = Module.cwrap('mp_js_process_char', 'number', ['number']); @@ -69,9 +69,9 @@ var mainProgram = function() } }); } else { - mp_js_do_str(contents); + process.exitCode = mp_js_do_str(contents); } } } -Module["onRuntimeInitialized"] = mainProgram; \ No newline at end of file +Module["onRuntimeInitialized"] = mainProgram; From bd6fed8201a818a96611e56ecc521c23cf5255f4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 28 Apr 2019 22:17:42 +1000 Subject: [PATCH 0031/1299] javascript/Makefile: Fix unrepresentable float error by using clamp. Otherwise converting large floats to ints will fail (as seen by the builtin_float_hash.py test). --- ports/javascript/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/javascript/Makefile b/ports/javascript/Makefile index 9b0f4d89c0c56..7309dfa481320 100644 --- a/ports/javascript/Makefile +++ b/ports/javascript/Makefile @@ -44,7 +44,7 @@ OBJ = $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -JSFLAGS = -O0 -s EXPORTED_FUNCTIONS="['_mp_js_init', '_mp_js_init_repl', '_mp_js_do_str', '_mp_js_process_char', '_mp_hal_get_interrupt_char', '_mp_keyboard_interrupt']" -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" --memory-init-file 0 --js-library library.js +JSFLAGS = -O0 -s EXPORTED_FUNCTIONS="['_mp_js_init', '_mp_js_init_repl', '_mp_js_do_str', '_mp_js_process_char', '_mp_hal_get_interrupt_char', '_mp_keyboard_interrupt']" -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" -s "BINARYEN_TRAP_MODE='clamp'" --memory-init-file 0 --js-library library.js all: $(BUILD)/micropython.js From d1dea4f57701b9464e3d6c45a5814d58fb0795f9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 28 Apr 2019 22:39:41 +1000 Subject: [PATCH 0032/1299] javascript/library: Print data as raw bytes to stdout so unicode works. --- ports/javascript/library.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ports/javascript/library.js b/ports/javascript/library.js index 85fa3e2edd1be..9aab3e4320aa1 100644 --- a/ports/javascript/library.js +++ b/ports/javascript/library.js @@ -27,10 +27,12 @@ mergeInto(LibraryManager.library, { mp_js_write: function(ptr, len) { for (var i = 0; i < len; ++i) { - c = String.fromCharCode(getValue(ptr + i, 'i8')); if (typeof window === 'undefined') { - process.stdout.write(c); + var b = Buffer.alloc(1); + b.writeInt8(getValue(ptr + i, 'i8')); + process.stdout.write(b); } else { + var c = String.fromCharCode(getValue(ptr + i, 'i8')); var mp_js_stdout = document.getElementById('mp_js_stdout'); var print = new Event('print'); print.data = c; From 8031b7a25c21fb864fe9dd1fa40740030be66c11 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 29 Apr 2019 16:31:32 +1000 Subject: [PATCH 0033/1299] stm32/powerctrl: Deselect PLLSAI as 48MHz src before turning off PLLSAI. On the STM32F722 (at least, but STM32F767 is not affected) the CK48MSEL bit must be deselected before PLLSAION is turned off, or else the 48MHz peripherals (RNG, SDMMC, USB) may get stuck without a clock source. In such "lock up" cases it seems that these peripherals are still being clocked from the PLLSAI even though the CK48MSEL bit is turned off. A hard reset does not get them out of this stuck state. Enabling the PLLSAI and then disabling it does get them out. A test case to see this is: import machine, pyb for i in range(100): machine.freq(122_000000) machine.freq(120_000000) print(i, [pyb.rng() for _ in range(4)]) On occasion the RNG will just return 0's, but will get fixed again on the next loop (when PLLSAI is enabled by the change to a SYSCLK of 122MHz). Fixes issue #4696. --- ports/stm32/powerctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 669e568f8a2d6..42bd262c275c0 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -54,8 +54,6 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk } } RCC->DCKCFGR2 |= RCC_DCKCFGR2_CK48MSEL; - } else { - RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_CK48MSEL; } // If possible, scale down the internal voltage regulator to save power @@ -208,6 +206,8 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t } #if defined(STM32F7) + // Deselect PLLSAI as 48MHz source if we were using it + RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_CK48MSEL; // Turn PLLSAI off because we are changing PLLM (which drives PLLSAI) RCC->CR &= ~RCC_CR_PLLSAION; #endif From fbd4e61e57185c0e9eb1aa7ced25926a140b23c9 Mon Sep 17 00:00:00 2001 From: Krono Date: Fri, 6 Jul 2018 12:06:11 +0200 Subject: [PATCH 0034/1299] esp32/machine_wdt: Add timeout arg to select interval, make WDT panic. The machine.WDT() now accepts the "timeout" keyword argument to select the WDT interval. And the WDT is changed to panic mode which means it will reset the device if the interval expires (instead of just printing an error message). --- ports/esp32/machine_wdt.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/ports/esp32/machine_wdt.c b/ports/esp32/machine_wdt.c index 88a58f056a1fd..5c4732f4b659d 100644 --- a/ports/esp32/machine_wdt.c +++ b/ports/esp32/machine_wdt.c @@ -41,21 +41,34 @@ typedef struct _machine_wdt_obj_t { STATIC machine_wdt_obj_t wdt_default = {{&machine_wdt_type}}; -STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); +STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_id, ARG_timeout }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} } + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - mp_int_t id = 0; - if (n_args > 0) { - id = mp_obj_get_int(args[0]); + if (args[ARG_id].u_int != 0) { + mp_raise_ValueError(NULL); } - switch (id) { - case 0: - esp_task_wdt_add(NULL); - return &wdt_default; - default: - mp_raise_ValueError(NULL); + // Convert milliseconds to seconds (esp_task_wdt_init needs seconds) + args[ARG_timeout].u_int /= 1000; + + if (args[ARG_timeout].u_int <= 0) { + mp_raise_ValueError("WDT timeout too short"); + } + + mp_int_t rs_code = esp_task_wdt_init(args[ARG_timeout].u_int, true); + if (rs_code != ESP_OK) { + mp_raise_OSError(rs_code); } + + esp_task_wdt_add(NULL); + + return &wdt_default; } STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) { From 9c7c082396f717a8a8eb845a0af407e78d38165f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 1 Mar 2019 23:48:16 +0300 Subject: [PATCH 0035/1299] extmod/modussl_mbedtls: Support non-blocking handshake. For this, add wrap_socket(do_handshake=False) param. CPython doesn't have such a param at a module's global function, and at SSLContext.wrap_socket() it has do_handshake_on_connect param, but that uselessly long. Beyond that, make write() handle not just MBEDTLS_ERR_SSL_WANT_WRITE, but also MBEDTLS_ERR_SSL_WANT_READ, as during handshake, write call may be actually preempted by need to read next handshake message from peer. Likewise, for read(). And even after the initial negotiation, situations like that may happen e.g. with renegotiation. Both MBEDTLS_ERR_SSL_WANT_READ and MBEDTLS_ERR_SSL_WANT_WRITE are however mapped to the same None return code. The idea is that if the same read()/write() method is called repeatedly, the progress will be made step by step anyway. The caveat is if user wants to add the underlying socket to uselect.poll(). To be reliable, in this case, the socket should be polled for both POLL_IN and POLL_OUT, as we don't know the actual expected direction. But that's actually problematic. Consider for example that write() ends with MBEDTLS_ERR_SSL_WANT_READ, but gets converted to None. We put the underlying socket on pull using POLL_IN|POLL_OUT but that probably returns immediately with POLL_OUT, as underlyings socket is writable. We call the same ussl write() again, which again results in MBEDTLS_ERR_SSL_WANT_READ, etc. We thus go into busy-loop. So, the handling in this patch is temporary and needs fixing. But exact way to fix it is not clear. One way is to provide explicit function for handshake (CPython has do_handshake()), and let *that* return distinct codes like WANT_READ/WANT_WRITE. But as mentioned above, past the initial handshake, such situation may happen again with at least renegotiation. So apparently, the only robust solution is to return "out of bound" special sentinels like WANT_READ/WANT_WRITE from read()/write() directly. CPython throws exceptions for these, but those are expensive to adopt that way for efficiency-conscious implementation like MicroPython. --- extmod/modussl_mbedtls.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 348bba4c80828..94863be57a9f7 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Linaro Ltd. + * Copyright (c) 2019 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -60,6 +61,7 @@ struct ssl_args { mp_arg_val_t cert; mp_arg_val_t server_side; mp_arg_val_t server_hostname; + mp_arg_val_t do_handshake; }; STATIC const mp_obj_type_t ussl_socket_type; @@ -184,10 +186,12 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { assert(ret == 0); } - while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - printf("mbedtls_ssl_handshake error: -%x\n", -ret); - goto cleanup; + if (args->do_handshake.u_bool) { + while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + printf("mbedtls_ssl_handshake error: -%x\n", -ret); + goto cleanup; + } } } @@ -238,6 +242,11 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc } if (ret == MBEDTLS_ERR_SSL_WANT_READ) { ret = MP_EWOULDBLOCK; + } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + // If handshake is not finished, read attempt may end up in protocol + // wanting to write next handshake message. The same may happen with + // renegotation. + ret = MP_EWOULDBLOCK; } *errcode = ret; return MP_STREAM_ERROR; @@ -252,6 +261,11 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in } if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { ret = MP_EWOULDBLOCK; + } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + // If handshake is not finished, write attempt may end up in protocol + // wanting to read next handshake message. The same may happen with + // renegotation. + ret = MP_EWOULDBLOCK; } *errcode = ret; return MP_STREAM_ERROR; @@ -321,6 +335,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; // TODO: Check that sock implements stream protocol From c76445315f836eb75835814ebe97e14107adbf0f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 1 Mar 2019 23:48:16 +0300 Subject: [PATCH 0036/1299] extmod/modussl_axtls: Add non-blocking mode support. It consists of: 1. "do_handhake" param (default True) to wrap_socket(). If it's False, handshake won't be performed by wrap_socket(), as it would be done in blocking way normally. Instead, SSL socket can be set to non-blocking mode, and handshake would be performed before the first read/write request (by just returning EAGAIN to these requests, while instead reading/writing/ processing handshake over the connection). Unfortunately, axTLS doesn't really support non-blocking handshake correctly. So, while framework for this is implemented on MicroPython's module side, in case of axTLS, it won't work reliably. 2. Implementation of .setblocking() method. It must be called on SSL socket for blocking vs non-blocking operation to be handled correctly (for example, it's not enough to wrap non-blocking socket with wrap_socket() call - resulting SSL socket won't be itself non-blocking). Note that .setblocking() propagates call to the underlying socket object, as expected. --- extmod/modussl_axtls.c | 55 ++++++++++++++++++++++------------ tests/extmod/ussl_basic.py.exp | 1 - 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 2dab6ff49146c..b559b1358002e 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015-2017 Paul Sokolovsky + * Copyright (c) 2015-2019 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,6 +41,7 @@ typedef struct _mp_obj_ssl_socket_t { SSL *ssl_sock; byte *buf; uint32_t bytes_left; + bool blocking; } mp_obj_ssl_socket_t; struct ssl_args { @@ -48,6 +49,7 @@ struct ssl_args { mp_arg_val_t cert; mp_arg_val_t server_side; mp_arg_val_t server_hostname; + mp_arg_val_t do_handshake; }; STATIC const mp_obj_type_t ussl_socket_type; @@ -62,8 +64,12 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { o->buf = NULL; o->bytes_left = 0; o->sock = sock; + o->blocking = true; uint32_t options = SSL_SERVER_VERIFY_LATER; + if (!args->do_handshake.u_bool) { + options |= SSL_CONNECT_IN_PARTS; + } if (args->key.u_obj != mp_const_none) { options |= SSL_NO_DEFAULT_KEY; } @@ -97,17 +103,14 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext); - int res = ssl_handshake_status(o->ssl_sock); - // Pointer to SSL_EXTENSIONS as being passed to ssl_client_new() - // is saved in ssl_sock->extensions. - // As of axTLS 2.1.3, extensions aren't used beyond the initial - // handshake, and that's pretty much how it's expected to be. So - // we allocate them on stack and reset the pointer after handshake. + if (args->do_handshake.u_bool) { + int res = ssl_handshake_status(o->ssl_sock); - if (res != SSL_OK) { - printf("ssl_handshake_status: %d\n", res); - ssl_display_error(res); - mp_raise_OSError(MP_EIO); + if (res != SSL_OK) { + printf("ssl_handshake_status: %d\n", res); + ssl_display_error(res); + mp_raise_OSError(MP_EIO); + } } } @@ -133,8 +136,18 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc mp_int_t r = ssl_read(o->ssl_sock, &o->buf); if (r == SSL_OK) { // SSL_OK from ssl_read() means "everything is ok, but there's - // no user data yet". So, we just keep reading. - continue; + // no user data yet". It may happen e.g. if handshake is not + // finished yet. The best way we can treat it is by returning + // EAGAIN. This may be a bit unexpected in blocking mode, but + // default is to perform complete handshake in constructor, so + // this should not happen in blocking mode. On the other hand, + // in nonblocking mode EAGAIN (comparing to the alternative of + // looping) is really preferrable. + if (o->blocking) { + continue; + } else { + goto eagain; + } } if (r < 0) { if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) { @@ -142,6 +155,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc return 0; } if (r == SSL_EAGAIN) { +eagain: r = MP_EAGAIN; } *errcode = r; @@ -187,12 +201,14 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i } STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { - // Currently supports only blocking mode - (void)self_in; - if (!mp_obj_is_true(flag_in)) { - mp_raise_NotImplementedError(NULL); - } - return mp_const_none; + mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in); + mp_obj_t sock = o->sock; + mp_obj_t dest[3]; + mp_load_method(sock, MP_QSTR_setblocking, dest); + dest[2] = flag_in; + mp_obj_t res = mp_call_method_n_kw(1, 0, dest); + o->blocking = mp_obj_is_true(flag_in); + return res; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); @@ -234,6 +250,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; // TODO: Check that sock implements stream protocol diff --git a/tests/extmod/ussl_basic.py.exp b/tests/extmod/ussl_basic.py.exp index cb9c51f7a1263..57eed8c57f4d9 100644 --- a/tests/extmod/ussl_basic.py.exp +++ b/tests/extmod/ussl_basic.py.exp @@ -4,6 +4,5 @@ wrap_socket: OSError(5,) setblocking: NotImplementedError 4 b'' -read: OSError(-261,) read: OSError(9,) write: OSError(9,) From 7b5400134b6d121741234cc99313145c0edf28c2 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 1 Mar 2019 23:48:16 +0300 Subject: [PATCH 0037/1299] tests/ussl_basic: Disable setblocking() calls. Now that setblocking() is implemented in modussl_axtls, it calls into the underlying stream object, and io.BytesIO doesn't have setblocking(). --- tests/extmod/ussl_basic.py | 13 +++++++------ tests/extmod/ussl_basic.py.exp | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/extmod/ussl_basic.py b/tests/extmod/ussl_basic.py index e8710ed51ab4b..a040fc20ca184 100644 --- a/tests/extmod/ussl_basic.py +++ b/tests/extmod/ussl_basic.py @@ -20,12 +20,13 @@ # print print(repr(ss)[:12]) -# setblocking -try: - ss.setblocking(False) -except NotImplementedError: - print('setblocking: NotImplementedError') -ss.setblocking(True) +# setblocking() propagates call to the underlying stream object, and +# io.BytesIO doesn't have setblocking() (in CPython too). +#try: +# ss.setblocking(False) +#except NotImplementedError: +# print('setblocking: NotImplementedError') +#ss.setblocking(True) # write print(ss.write(b'aaaa')) diff --git a/tests/extmod/ussl_basic.py.exp b/tests/extmod/ussl_basic.py.exp index 57eed8c57f4d9..5282338319efb 100644 --- a/tests/extmod/ussl_basic.py.exp +++ b/tests/extmod/ussl_basic.py.exp @@ -1,8 +1,8 @@ ssl_handshake_status: -256 wrap_socket: OSError(5,) <_SSLSocket -setblocking: NotImplementedError 4 b'' +read: OSError(-261,) read: OSError(9,) write: OSError(9,) From 859596ce25bcaa9b6104f16b8b55d0832c55e3f8 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 29 Apr 2019 12:00:13 +1000 Subject: [PATCH 0038/1299] lib/utils: Make pyexec_file_if_exists run frozen scripts if they exist. So that boot.py and/or main.py can be frozen (either as STR or MPY) in the same way that other scripts are frozen. Frozen scripts have preference to scripts in the VFS. --- lib/utils/pyexec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index 946a97a00a395..adb16937d0ad0 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -542,8 +542,12 @@ int pyexec_file(const char *filename) { } int pyexec_file_if_exists(const char *filename) { - mp_import_stat_t stat = mp_import_stat(filename); - if (stat != MP_IMPORT_STAT_FILE) { + #if MICROPY_MODULE_FROZEN + if (mp_frozen_stat(filename) == MP_IMPORT_STAT_FILE) { + return pyexec_frozen_module(filename); + } + #endif + if (mp_import_stat(filename) != MP_IMPORT_STAT_FILE) { return 1; // success (no file is the same as an empty file executing without fail) } return pyexec_file(filename); From 245916259926777b1b157c679785597572576f57 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 1 May 2019 12:41:07 +1000 Subject: [PATCH 0039/1299] lib/utils/interrupt_char: Invalidate interrupt char at start up. Otherwise mp_interrupt_char will have a value of zero on start up (because it's in the BSS) and a KeyboardInterrupt may be raised during start up. For example this can occur if there is a UART attached to the REPL which sends spurious null bytes when the device turns on. --- lib/utils/interrupt_char.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/interrupt_char.c b/lib/utils/interrupt_char.c index fca0f95b5bf4a..43d45e5aec351 100644 --- a/lib/utils/interrupt_char.c +++ b/lib/utils/interrupt_char.c @@ -29,7 +29,7 @@ #if MICROPY_KBD_EXCEPTION -int mp_interrupt_char; +int mp_interrupt_char = -1; void mp_hal_set_interrupt_char(int c) { if (c != -1) { From ff0306dfa5ceee8c2c52ae82c4336e5c23d36176 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 1 May 2019 13:08:05 +1000 Subject: [PATCH 0040/1299] stm32/usb: Remove mp_hal_set_interrupt_char now that it's reset at boot. --- ports/stm32/usb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index e81225e60577a..18841fdee4015 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -115,7 +115,6 @@ void pyb_usb_init0(void) { #if MICROPY_HW_USB_ENABLE_CDC2 usb_device.usbd_cdc2_itf.attached_to_repl = false; #endif - mp_hal_set_interrupt_char(-1); MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL; } From cbeac903e86bfb0c50f55960201f9eaa9d45745a Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 1 May 2019 14:50:27 +1000 Subject: [PATCH 0041/1299] stm32/main: Increase default UART REPL rx buffer from 64 to 260 bytes. This allows the UART to buffer at least 256 bytes (taking into account the extra byte needed by the ring buffer, and word alignment). --- ports/stm32/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 0bdbbd481d452..a37c6f89790e0 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -78,7 +78,7 @@ STATIC fs_user_mount_t fs_user_mount_flash; #if defined(MICROPY_HW_UART_REPL) #ifndef MICROPY_HW_UART_REPL_RXBUF -#define MICROPY_HW_UART_REPL_RXBUF (64) +#define MICROPY_HW_UART_REPL_RXBUF (260) #endif STATIC pyb_uart_obj_t pyb_uart_repl_obj; STATIC uint8_t pyb_uart_repl_rxbuf[MICROPY_HW_UART_REPL_RXBUF]; From 34a7d7ebebc93bf9c4f166b0b523ceab844c7d91 Mon Sep 17 00:00:00 2001 From: stijn Date: Tue, 30 Apr 2019 11:05:57 +0200 Subject: [PATCH 0042/1299] unix/gcollect: Make sure stack/regs get captured properly for GC. When building with link time optimization enabled it is possible both gc_collect() and gc_collect_regs_and_stack() get inlined into gc_alloc() which can result in the regs variable being pushed on the stack earlier than some of the registers. Depending on the calling convention, those registers might however contain pointers to blocks which have just been allocated in the caller of gc_alloc(). Then those pointers end up higher on the stack than regs, aren't marked by gc_collect_root() and hence get sweeped, even though they're still in use. As reported in #4652 this happened for in 32-bit msvc release builds: mp_lexer_new() does two consecutive allocations and the latter triggered a gc_collect() which would sweep the memory of the first allocation again. --- ports/unix/gccollect.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ports/unix/gccollect.c b/ports/unix/gccollect.c index 02f6fc91a8400..ddc2d92c3b90c 100644 --- a/ports/unix/gccollect.c +++ b/ports/unix/gccollect.c @@ -149,9 +149,14 @@ STATIC void gc_helper_get_regs(regs_t arr) { #endif // MICROPY_GCREGS_SETJMP // this function is used by mpthreadport.c -void gc_collect_regs_and_stack(void); - -void gc_collect_regs_and_stack(void) { +MP_NOINLINE void gc_collect_regs_and_stack(void); + +// Explicitly mark this as noinline to make sure the regs variable +// is effectively at the top of the stack: otherwise, in builds where +// LTO is enabled and a lot of inlining takes place we risk a stack +// layout where regs is lower on the stack than pointers which have +// just been allocated but not yet marked, and get incorrectly sweeped. +MP_NOINLINE void gc_collect_regs_and_stack(void) { regs_t regs; gc_helper_get_regs(regs); // GC stack (and regs because we captured them) From 9ef784dcc6aa2abd7325b43f3d1613b8ac5d9f3f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 1 May 2019 15:24:21 +1000 Subject: [PATCH 0043/1299] py/asmthumb: Support asm_thumb code running on normal ARM processors. With this change, @micropython.asm_thumb functions will work on standard ARM processors (that are in ARM state by default), in scripts and precompiled .mpy files. Addresses issue #4675. --- py/asmthumb.c | 17 +++++++++++++++++ py/compile.c | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/py/asmthumb.c b/py/asmthumb.c index e6bba7ea60ebe..68fb8f29eed36 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -33,6 +33,8 @@ // wrapper around everything in this file #if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB +#include "py/mpstate.h" +#include "py/persistentcode.h" #include "py/mphal.h" #include "py/asmthumb.h" @@ -118,6 +120,21 @@ STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) { void asm_thumb_entry(asm_thumb_t *as, int num_locals) { assert(num_locals >= 0); + // If this Thumb machine code is run from ARM state then add a prelude + // to switch to Thumb state for the duration of the function. + #if MICROPY_DYNAMIC_COMPILER || MICROPY_EMIT_ARM || (defined(__arm__) && !defined(__thumb2__)) + #if MICROPY_DYNAMIC_COMPILER + if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_ARMV6) + #endif + { + asm_thumb_op32(as, 0x4010, 0xe92d); // push {r4, lr} + asm_thumb_op32(as, 0xe009, 0xe28f); // add lr, pc, 8 + 1 + asm_thumb_op32(as, 0xff3e, 0xe12f); // blx lr + asm_thumb_op32(as, 0x4010, 0xe8bd); // pop {r4, lr} + asm_thumb_op32(as, 0xff1e, 0xe12f); // bx lr + } + #endif + // work out what to push and how many extra spaces to reserve on stack // so that we have enough for all locals and it's aligned an 8-byte boundary // we push extra regs (r1, r2, r3) to help do the stack adjustment diff --git a/py/compile.c b/py/compile.c index 4919a165955f4..01e4ff9b650a2 100644 --- a/py/compile.c +++ b/py/compile.c @@ -124,7 +124,7 @@ STATIC const emit_inline_asm_method_table_t *emit_asm_table[] = { NULL, NULL, NULL, - NULL, + &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, From e70c438c71cbc3c44b8370ab5504658328b3ced9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 1 May 2019 15:31:00 +1000 Subject: [PATCH 0044/1299] mpy-cross: Automatically select ARMV6 arch when running on such a host. --- mpy-cross/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 6e5af2739bc40..7bf207596241a 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -196,6 +196,8 @@ MP_NOINLINE int main_(int argc, char **argv) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86; #elif defined(__x86_64__) mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64; + #elif defined(__arm__) && !defined(__thumb2__) + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6; #else mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE; #endif From 3fbf32b947eb798cf4a717adc23026e677d06bf0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 2 May 2019 13:00:00 +1000 Subject: [PATCH 0045/1299] stm32/powerctrl: Support changing frequency when HSI is clock source. This patch makes pllvalues.py generate two tables: one for when HSI is used and one for when HSE is used. The correct table is then selected at compile time via the existing MICROPY_HW_CLK_USE_HSI. --- ports/stm32/boards/pllvalues.py | 59 ++++++++++++++++++++++----------- ports/stm32/powerctrl.c | 10 ++++-- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/ports/stm32/boards/pllvalues.py b/ports/stm32/boards/pllvalues.py index 4b090c455b47c..da1b81216fdf4 100644 --- a/ports/stm32/boards/pllvalues.py +++ b/ports/stm32/boards/pllvalues.py @@ -5,6 +5,7 @@ """ from __future__ import print_function +import re def close_int(x): return abs(x - round(x)) < 0.01 @@ -109,12 +110,18 @@ def verify_pll(hse, pll): assert 1 <= vco_in <= 2 assert 192 <= vco_out <= 432 +def compute_pll_table(source_clk, relax_pll48): + valid_plls = [] + for sysclk in range(2, 217, 2): + pll = compute_pll2(source_clk, sysclk, relax_pll48) + if pll is not None: + verify_pll(source_clk, pll) + valid_plls.append((sysclk, pll)) + return valid_plls + def generate_c_table(hse, valid_plls): - valid_plls = valid_plls + [(16, (0, 0, 2, 0))] - if hse < 16: - valid_plls.append((hse, (1, 0, 2, 0))) valid_plls.sort() - print("// (M, P/2-1, SYS) values for %u MHz HSE" % hse) + print("// (M, P/2-1, SYS) values for %u MHz source" % hse) print("static const uint16_t pll_freq_table[%u] = {" % len(valid_plls)) for sys, (M, N, P, Q) in valid_plls: print(" (%u << 10) | (%u << 8) | %u," % (M, P // 2 - 1, sys)) @@ -137,6 +144,8 @@ def main(): c_table = False relax_pll48 = False + hse = None + hsi = None while True: if argv[0] == '-c': @@ -153,32 +162,44 @@ def main(): sys.exit(1) if argv[0].startswith("file:"): - # extract HSE_VALUE from header file + # extract HSE_VALUE, and optionally HSI_VALUE, from header file + regex = re.compile(r'#define +(HSE_VALUE|HSI_VALUE) +\(\(uint32_t\)([0-9]+)\)') with open(argv[0][5:]) as f: for line in f: line = line.strip() - if line.startswith("#define") and line.find("HSE_VALUE") != -1: - idx_start = line.find("((uint32_t)") + 11 - idx_end = line.find(")", idx_start) - hse = int(line[idx_start:idx_end]) // 1000000 - break - else: + m = regex.match(line) + if m: + val = int(m.group(2)) // 1000000 + if m.group(1) == 'HSE_VALUE': + hse = val + else: + hsi = val + if hse is None: raise ValueError("%s does not contain a definition of HSE_VALUE" % argv[0]) + if hsi is not None and hsi > 16: + # Currently, a HSI value greater than 16MHz is not supported + hsi = None else: # HSE given directly as an integer hse = int(argv[0]) - valid_plls = [] - for sysclk in range(2, 217, 2): - pll = compute_pll2(hse, sysclk, relax_pll48) - if pll is not None: - verify_pll(hse, pll) - valid_plls.append((sysclk, pll)) + hse_valid_plls = compute_pll_table(hse, relax_pll48) + if hsi is not None: + hsi_valid_plls = compute_pll_table(hsi, relax_pll48) if c_table: - generate_c_table(hse, valid_plls) + print('#if MICROPY_HW_CLK_USE_HSI') + if hsi is not None: + hsi_valid_plls.append((hsi, (0, 0, 2, 0))) + generate_c_table(hsi, hsi_valid_plls) + print('#else') + if hsi is not None: + hse_valid_plls.append((hsi, (0, 0, 2, 0))) + hse_valid_plls.append((hse, (1, 0, 2, 0))) + generate_c_table(hse, hse_valid_plls) + print('#endif') else: - print_table(hse, valid_plls) + print_table(hse, hse_valid_plls) if __name__ == "__main__": main() diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 42bd262c275c0..c3792be3ed7f2 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -136,7 +136,7 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t } // Default PLL parameters that give 48MHz on PLL48CK - uint32_t m = HSE_VALUE / 1000000, n = 336, p = 2, q = 7; + uint32_t m = MICROPY_HW_CLK_VALUE / 1000000, n = 336, p = 2, q = 7; uint32_t sysclk_source; bool need_pllsai = false; @@ -157,7 +157,7 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t // use PLL sysclk_source = RCC_SYSCLKSOURCE_PLLCLK; uint32_t vco_out = sys * p; - n = vco_out * m / (HSE_VALUE / 1000000); + n = vco_out * m / (MICROPY_HW_CLK_VALUE / 1000000); q = vco_out / 48; #if defined(STM32F7) need_pllsai = vco_out % 48 != 0; @@ -178,7 +178,11 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) { // Set HSE as system clock source to allow modification of the PLL configuration // We then change to PLL after re-configuring PLL + #if MICROPY_HW_CLK_USE_HSI + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + #else RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; + #endif } else { // Directly set the system clock source as desired RCC_ClkInitStruct.SYSCLKSource = sysclk_source; @@ -217,6 +221,8 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t RCC_OscInitTypeDef RCC_OscInitStruct; RCC_OscInitStruct.OscillatorType = MICROPY_HW_RCC_OSCILLATOR_TYPE; RCC_OscInitStruct.HSEState = MICROPY_HW_RCC_HSE_STATE; + RCC_OscInitStruct.HSIState = MICROPY_HW_RCC_HSI_STATE; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = MICROPY_HW_RCC_PLL_SRC; RCC_OscInitStruct.PLL.PLLM = m; From a974f2dc6e45dc1fde88863df6b90dcaebf5bfe8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 2 May 2019 14:53:26 +1000 Subject: [PATCH 0046/1299] stm32/flash: Fix bug computing page number for L432 page erase. --- ports/stm32/flash.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index e1cf707d3431c..56896a7037dda 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -122,6 +122,12 @@ static uint32_t get_page(uint32_t addr) { } #endif +#elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE) + +static uint32_t get_page(uint32_t addr) { + return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; +} + #endif uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) { @@ -167,7 +173,7 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) { #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; - EraseInitStruct.Page = flash_dest; + EraseInitStruct.Page = get_page(flash_dest); EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; #elif defined(STM32L4) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); From 1b956ec81701ad9ae36e8e0fd625eff32e3e2a3d Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 19 Apr 2019 15:15:18 +1000 Subject: [PATCH 0047/1299] stm32: Add support for F413 MCUs. Includes: - Support for CAN3. - Support for UART9 and UART10. - stm32f413xg.ld and stm32f413xh.ld linker scripts. - stm32f413_af.csv alternate function mapping. - startup_stm32f413xx.s because F413 has different interrupt vector table. - Memory configuration with: 240K filesystem, 240K heap, 16K stack. --- ports/stm32/adc.c | 2 +- ports/stm32/boards/startup_stm32f413xx.s | 580 +++++++++++++++++++++++ ports/stm32/boards/stm32f413_af.csv | 116 +++++ ports/stm32/boards/stm32f413xg.ld | 31 ++ ports/stm32/boards/stm32f413xh.ld | 31 ++ ports/stm32/can.c | 53 ++- ports/stm32/can.h | 1 + ports/stm32/flashbdev.c | 9 + ports/stm32/machine_uart.c | 8 + ports/stm32/mpconfigboard_common.h | 19 +- ports/stm32/mpconfigport.h | 2 +- ports/stm32/stm32_it.c | 36 ++ ports/stm32/uart.c | 50 ++ ports/stm32/uart.h | 2 + 14 files changed, 925 insertions(+), 15 deletions(-) create mode 100644 ports/stm32/boards/startup_stm32f413xx.s create mode 100644 ports/stm32/boards/stm32f413_af.csv create mode 100644 ports/stm32/boards/stm32f413xg.ld create mode 100644 ports/stm32/boards/stm32f413xh.ld diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 73588e4a3f172..4f923245625b1 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -137,7 +137,7 @@ #define VBAT_DIV (2) #elif defined(STM32F427xx) || defined(STM32F429xx) || \ defined(STM32F437xx) || defined(STM32F439xx) || \ - defined(STM32F446xx) || \ + defined(STM32F446xx) || defined(STM32F413xx) || \ defined(STM32F722xx) || defined(STM32F723xx) || \ defined(STM32F732xx) || defined(STM32F733xx) || \ defined(STM32F746xx) || defined(STM32F765xx) || \ diff --git a/ports/stm32/boards/startup_stm32f413xx.s b/ports/stm32/boards/startup_stm32f413xx.s new file mode 100644 index 0000000000000..64108ad38d9a7 --- /dev/null +++ b/ports/stm32/boards/startup_stm32f413xx.s @@ -0,0 +1,580 @@ +/** + ****************************************************************************** + * @file startup_stm32f413xx.s + * @author MCD Application Team + * @brief STM32F413xx Devices vector table for GCC based toolchains. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + /*bl __libc_init_array*/ +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FSMC_IRQHandler /* FSMC */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6, DAC1 and DAC2 */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word DFSDM1_FLT0_IRQHandler /* DFSDM1 Filter0 */ + .word DFSDM1_FLT1_IRQHandler /* DFSDM1 Filter1 */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word CAN3_TX_IRQHandler /* CAN3 TX */ + .word CAN3_RX0_IRQHandler /* CAN3 RX0 */ + .word CAN3_RX1_IRQHandler /* CAN3 RX1 */ + .word CAN3_SCE_IRQHandler /* CAN3 SCE */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word RNG_IRQHandler /* RNG */ + .word FPU_IRQHandler /* FPU */ + .word UART7_IRQHandler /* UART7 */ + .word UART8_IRQHandler /* UART8 */ + .word SPI4_IRQHandler /* SPI4 */ + .word SPI5_IRQHandler /* SPI5 */ + .word 0 /* Reserved */ + .word SAI1_IRQHandler /* SAI1 */ + .word UART9_IRQHandler /* UART9 */ + .word UART10_IRQHandler /* UART10 */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word QUADSPI_IRQHandler /* QuadSPI */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word FMPI2C1_EV_IRQHandler /* FMPI2C1 Event */ + .word FMPI2C1_ER_IRQHandler /* FMPI2C1 Error */ + .word LPTIM1_IRQHandler /* LPTIM1 */ + .word DFSDM2_FLT0_IRQHandler /* DFSDM2 Filter0 */ + .word DFSDM2_FLT1_IRQHandler /* DFSDM2 Filter1 */ + .word DFSDM2_FLT2_IRQHandler /* DFSDM2 Filter2 */ + .word DFSDM2_FLT3_IRQHandler /* DFSDM2 Filter3 */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FSMC_IRQHandler + .thumb_set FSMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak DFSDM1_FLT0_IRQHandler + .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler + + .weak DFSDM1_FLT1_IRQHandler + .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak CAN3_TX_IRQHandler + .thumb_set CAN3_TX_IRQHandler,Default_Handler + + .weak CAN3_RX0_IRQHandler + .thumb_set CAN3_RX0_IRQHandler,Default_Handler + + .weak CAN3_RX1_IRQHandler + .thumb_set CAN3_RX1_IRQHandler,Default_Handler + + .weak CAN3_SCE_IRQHandler + .thumb_set CAN3_SCE_IRQHandler,Default_Handler + + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak UART9_IRQHandler + .thumb_set UART9_IRQHandler,Default_Handler + + .weak UART10_IRQHandler + .thumb_set UART10_IRQHandler,Default_Handler + + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler + + .weak FMPI2C1_EV_IRQHandler + .thumb_set FMPI2C1_EV_IRQHandler,Default_Handler + + .weak FMPI2C1_ER_IRQHandler + .thumb_set FMPI2C1_ER_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak DFSDM2_FLT0_IRQHandler + .thumb_set DFSDM2_FLT0_IRQHandler,Default_Handler + + .weak DFSDM2_FLT1_IRQHandler + .thumb_set DFSDM2_FLT1_IRQHandler,Default_Handler + + .weak DFSDM2_FLT2_IRQHandler + .thumb_set DFSDM2_FLT2_IRQHandler,Default_Handler + + .weak DFSDM2_FLT3_IRQHandler + .thumb_set DFSDM2_FLT3_IRQHandler,Default_Handler +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/boards/stm32f413_af.csv b/ports/stm32/boards/stm32f413_af.csv new file mode 100644 index 0000000000000..428ce44cfcbbe --- /dev/null +++ b/ports/stm32/boards/stm32f413_af.csv @@ -0,0 +1,116 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, +,,SYS_AF,TIM1/TIM2/LPTIM1,TIM3/TIM4/TIM5,TIM8/9/10/11/DFSDM2,I2C1/2/3/I2CFMP1,SPI1/2/3/4/I2S1/2/3/4,SPI2/3/4/5/I2S2/3/4/5/DFSDM1/2,SPI3/I2S3/USART1/2/3/DFSDM2,USART3/4/5/6/7/8/CAN1/DFSDM1,I2C2/I2C3/I2CFMP1/CAN1/2/TIM12/13/14/QUADSPI,SAI1/DFSDM1/DFSDM2/QUADSPI/FSMC/OTG1_FS,UART4/5/9/10/CAN3,FSMC /SDIO,,RNG,SYS_AF,ADC +PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,,,EVENTOUT,ADC1_IN0 +PortA,PA1,,TIM2_CH2,TIM5_CH2,,,SPI4_MOSI/I2S4_SD,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC1_IN1 +PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,I2S2_CKIN,,USART2_TX,,,,,FSMC_D4,,,EVENTOUT,ADC1_IN2 +PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,I2S2_MCK,,USART2_RX,,,SAI1_SD_B,,FSMC_D5,,,EVENTOUT,ADC1_IN3 +PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,DFSDM1_DATIN1,,,,FSMC_D6,,,EVENTOUT,ADC1_IN4 +PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,DFSDM1_CKIN1,,,,FSMC_D7,,,EVENTOUT,ADC1_IN5 +PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,I2S2_MCK,DFSDM2_CKIN1,,TIM13_CH1,QUADSPI_BK2_IO0,,SDIO_CMD,,,EVENTOUT,ADC1_IN6 +PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,DFSDM2_DATIN1,,TIM14_CH1,QUADSPI_BK2_IO1,,,,,EVENTOUT,ADC1_IN7 +PortA,PA8,MCO_1,TIM1_CH1,,,I2C3_SCL,,DFSDM1_CKOUT,USART1_CK,UART7_RX,,USB_FS_SOF,CAN3_RX,SDIO_D1,,,EVENTOUT, +PortA,PA9,,TIM1_CH2,,DFSDM2_CKIN3,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,USB_FS_VBUS,,SDIO_D2,,,EVENTOUT, +PortA,PA10,,TIM1_CH3,,DFSDM2_DATIN3,,SPI2_MOSI/I2S2_SD,SPI5_MOSI/I2S5_SD,USART1_RX,,,USB_FS_ID,,,,,EVENTOUT, +PortA,PA11,,TIM1_CH4,,DFSDM2_CKIN5,,SPI2_NSS/I2S2_WS,SPI4_MISO,USART1_CTS,USART6_TX,CAN1_RX,USB_FS_DM,UART4_RX,,,,EVENTOUT, +PortA,PA12,,TIM1_ETR,,DFSDM2_DATIN5,,SPI2_MISO,SPI5_MISO,USART1_RTS,USART6_RX,CAN1_TX,USB_FS_DP,UART4_TX,,,,EVENTOUT, +PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART1_TX,UART7_TX,,SAI1_MCLK_A,CAN3_TX,,,,EVENTOUT, +PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,SPI5_SCK/I2S5_CK,,,,,,,,,EVENTOUT,ADC1_IN8 +PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,SPI5_NSS/I2S5_WS,,DFSDM1_DATIN0,QUADSPI_CLK,,,,,,EVENTOUT,ADC1_IN9 +PortB,PB2,,LPTIM1_OUT,,,,,DFSDM1_CKIN0,,,QUADSPI_CLK,,,,,,EVENTOUT, +PortB,PB3,JTDO,TIM2_CH2,,,I2CFMP1_SDA,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,USART1_RX,UART7_RX,I2C2_SDA,SAI1_SD_A,CAN3_RX,,,,EVENTOUT, +PortB,PB4,JTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,I2S3ext_SD,UART7_TX,I2C3_SDA,SAI1_SCK_A,CAN3_TX,SDIO_D0,,,EVENTOUT, +PortB,PB5,,LPTIM1_IN1,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,SAI1_FS_A,UART5_RX,SDIO_D3,,,EVENTOUT, +PortB,PB6,,LPTIM1_ETR,TIM4_CH1,,I2C1_SCL,,DFSDM2_CKIN7,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,UART5_TX,SDIO_D0,,,EVENTOUT, +PortB,PB7,,LPTIM1_IN2,TIM4_CH2,,I2C1_SDA,,DFSDM2_DATIN7,USART1_RX,,,,,FSMC_NL,,,EVENTOUT, +PortB,PB8,,LPTIM1_OUT,TIM4_CH3,TIM10_CH1,I2C1_SCL,,SPI5_MOSI/I2S5_SD,DFSDM2_CKIN1,CAN1_RX,I2C3_SDA,,UART5_RX,SDIO_D4,,,EVENTOUT, +PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,DFSDM2_DATIN1,,CAN1_TX,I2C2_SDA,,UART5_TX,SDIO_D5,,,EVENTOUT, +PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,I2S3_MCK,USART3_TX,,I2CFMP4_SCL,DFSDM2_CKOUT,,SDIO_D7,,,EVENTOUT, +PortB,PB11,,TIM2_CH4,,,I2C2_SDA,I2S2_CKIN,,USART3_RX,,,,,,,,EVENTOUT, +PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,SPI4_NSS/I2S4_WS,SPI3_SCK/I2S3_CK,USART3__CK,CAN2_RX,DFSDM1_DATIN1,UART5_RX,FSMC_D13/FSMC_DA13,,,EVENTOUT, +PortB,PB13,,TIM1_CH1N,,,I2CFMP1_SMBA,SPI2_SCK/I2S2_CK,SPI4_SCK/I2S4_CK,,USART3_CTS,CAN2_TX,DFSDM1_CKIN1,UART5_TX,,,,EVENTOUT, +PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2CFMP1_SDA,SPI2_MISO,I2S2ext_SD,USART3_RTS,DFSDM1_DATIN2,TIM12_CH1,FSMC_D0,,SDIO_D6,,,EVENTOUT, +PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,I2CFMP1_SCL,SPI2_MOSI/I2S2_SD,,,DFSDM1_CKIN2,TIM12_CH2,,,SDIO_CK,,,EVENTOUT, +PortC,PC0,,LPTIM1_IN1,,DFSDM2_CKIN4,,,,SAI1_MCLK_B,,,,,,,,EVENTOUT,ADC1_IN10 +PortC,PC1,,LPTIM1_OUT,,DFSDM2_DATIN4,,,,SAI1_SD_B,,,,,,,,EVENTOUT,ADC1_IN11 +PortC,PC2,,LPTIM1_IN2,,DFSDM2_DATIN7,,SPI2_MISO,I2S2ext_SD,SAI1_SCK_B,DFSDM1_CKOUT,,,,FSMC_NWE,,,EVENTOUT,ADC1_IN12 +PortC,PC3,,LPTIM1_ETR,,DFSDM2_CKIN7,,SPI2_MOSI/I2S2_SD,,SAI1_FS_B,,,,,FSMC_A0,,,EVENTOUT,ADC1_IN13 +PortC,PC4,,,,DFSDM2_CKIN2,,I2S1_MCK,,,,,QUADSPI_BK2_IO2,,FSMC_NE4,,,EVENTOUT,ADC1_IN14 +PortC,PC5,,,,DFSDM2_DATIN2,I2CFMP1_SMBA,,,USART3_RX,,,QUADSPI_BK2_IO3,,FSMC_NOE,,,EVENTOUT,ADC1_IN15 +PortC,PC6,,,TIM3_CH1,TIM8_CH1,2CFMP1_SCL,I2S2_MCK,DFSDM1_CKIN3,DFSDM2_DATIN6,USART6_TX,,FSMC_D1,,SDIO_D6,,,EVENTOUT, +PortC,PC7,,,TIM3_CH2,TIM8_CH2,I2CFMP1_SDA,SPI2_SCK/I2S2_CK,I2S3_MCK,DFSDM2_CKIN6,USART6_RX,,DFSDM1_DATIN3,,SDIO_D7,,,EVENTOUT, +PortC,PC8,,,TIM3_CH3,TIM8_CH3,,,,DFSDM2_CKIN3,USART6_CK,QUADSPI_BK1_IO2,,,SDIO_D0,,,EVENTOUT, +PortC,PC9,MCO_2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S2_CKIN,,DFSDM2_DATIN3,,QUADSPI_BK1_IO0,,,SDIO_D1,,,EVENTOUT, +PortC,PC10,,,,DFSDM2_CKIN5,,,SPI3_SCK/I2S3_CK,USART3_TX,,QUADSPI_BK1_IO1,,,SDIO_D2,,,EVENTOUT, +PortC,PC11,,,,DFSDM2_DATIN5,,I2S3ext_SD,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,FSMC_D2,,SDIO_D3,,,EVENTOUT, +PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,FSMC_D3,,SDIO_CK,,,EVENTOUT, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, +PortD,PD0,,,,DFSDM2_CKIN6,,,,,,CAN1_RX,,UART4_RX,FSMC_D2/FSMC_DA2,,,EVENTOUT, +PortD,PD1,,,,DFSDM2_DATIN6,,,,,,CAN1_TX,,UART4_TX,FSMC_D3/FSMC_DA3,,,EVENTOUT, +PortD,PD2,,,TIM3_ETR,DFSDM2_CKOUT,,,,,UART5_RX,,FSMC_NWE,,SDIO_CMD,,,EVENTOUT, +PortD,PD3,TRACED1,,,,,SPI2_SCK/I2S2_CK,DFSDM1_DATIN0,USART2_CTS,,QUADSPI_CLK,,,FSMC_CLK,,,EVENTOUT, +PortD,PD4,,,,,,,DFSDM1_CKIN0,USART2_RTS,,,,,FSMC_NOE,,,EVENTOUT, +PortD,PD5,,,,DFSDM2_CKOUT,,,,USART2_TX,,,,,FSMC_NWE,,,EVENTOUT, +PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,DFSDM1_DATIN1,USART2_RX,,,,,FSMC_NWAIT,,,EVENTOUT, +PortD,PD7,,,,,,,DFSDM1_CKIN1,USART2_CK,,,,,FSMC_NE1,,,EVENTOUT, +PortD,PD8,,,,,,,,USART3_TX,,,,,FSMC_D13/FSMC_DA13,,,EVENTOUT, +PortD,PD9,,,,,,,,USART3_RX,,,,,FSMC_D14/FSMC_DA14,,,EVENTOUT, +PortD,PD10,,,,,,,,USART3_CK,UART4_TX,,,,FSMC_D15/FSMC_DA15,,,EVENTOUT, +PortD,PD11,,,,DFSDM2_DATIN2,I2CFMP1_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,,,FSMC_A16,,,EVENTOUT, +PortD,PD12,,,TIM4_CH1,DFSDM2_CKIN2,I2CFMP1_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,,,FSMC_A17,,,EVENTOUT, +PortD,PD13,,,TIM4_CH2,,I2CFMP1_SDA,,,,,QUADSPI_BK1_IO3,,,FSMC_A18,,,EVENTOUT, +PortD,PD14,,,TIM4_CH3,,I2CFMP1_SCL,,,,,,DFSDM2_CKIN0,UART9_RX,FSMC_D0/FSMC_DA0,,,EVENTOUT, +PortD,PD15,,,TIM4_CH4,,I2CFMP1_SDA,,,,,,DFSDM2_DATIN0,UART9_TX,FSMC_D1/FSMC_DA1,,,EVENTOUT, +PortE,PE0,,,TIM4_ETR,DFSDM2_CKIN4,,,,,UART8_RX,,,,FSMC_NBL0,,,EVENTOUT, +PortE,PE1,,,,DFSDM2_DATIN4,,,,,UART8_TX,,,,FSMC_NBL1,,,EVENTOUT, +PortE,PE2,TRACECLK,,,,,SPI4_SCK/I2S4_CK,SPI5_SCK/I2S5_CK,SAI1_MCLK_A,,QUADSPI_BK1_IO2,,UART10_RX,FSMC_A23,,,EVENTOUT, +PortE,PE3,TRACED0,,,,,,,SAI1_SD_B,,,,UART10_TX,FSMC_A19,,,EVENTOUT, +PortE,PE4,TRACED1,,,,,SPI4_NSS/I2S4_WS,SPI5_NSS/I2S5_WS,SAI1_SD_A,DFSDM1_DATIN3,,,,FSMC_A20,,,EVENTOUT, +PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SPI5_MISO,SAI1_SCK_A,DFSDM1_CKIN3,,,,FSMC_A21,,,EVENTOUT, +PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI/I2S4_SD,SPI5_MOSI/I2S5_SD,SAI1_FS_A,,,,,FSMC_A22,,,EVENTOUT, +PortE,PE7,,TIM1_ETR,,,,,DFSDM1_DATIN2,,UART7_RX,,QUADSPI_BK2_IO0,,FSMC_D4/FSMC_DA4,,,EVENTOUT, +PortE,PE8,,TIM1_CH1N,,,,,DFSDM1_CKIN2,,UART7_TX,,QUADSPI_BK2_IO1,,FSMC_D5/FSMC_DA5,,,EVENTOUT, +PortE,PE9,,TIM1_CH1,,,,,DFSDM1_CKOUT,,,,QUADSPI_BK2_IO2,,FSMC_D6/FSMC_DA6,,,EVENTOUT, +PortE,PE10,,TIM1_CH2N,,DFSDM2_DATIN0,,,,,,,QUADSPI_BK2_IO3,,FSMC_D7/FSMC_DA7,,,EVENTOUT, +PortE,PE11,,TIM1_CH2,,DFSDM2_CKIN0,,SPI4_NSS/I2S4_WS,SPI5_NSS/I2S5_WS,,,,,,FSMC_D8/FSMC_DA8,,,EVENTOUT, +PortE,PE12,,TIM1_CH3N,,DFSDM2_DATIN7,,SPI4_SCK/I2S4_CK,SPI5_SCK/I2S5_CK,,,,,,FSMC_D9/FSMC_DA9,,,EVENTOUT, +PortE,PE13,,TIM1_CH3,,DFSDM2_CKIN7,,SPI4_MISO,SPI5_MISO,,,,,,FSMC_D10/FSMC_DA10,,,EVENTOUT, +PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI/I2S4_SD,SPI5_MOSI/I2S5_SD,,,,DFSDM2_DATIN1,,FSMC_D11/FSMC_DA11,,,EVENTOUT, +PortE,PE15,,TIM1_BKIN,,,,,,,,,DFSDM2_CKIN1,,FSMC_D12/FSMC_DA12,,,EVENTOUT, +PortF,PF0,,,,,I2C2_SDA,,,,,,,,FSMC_A0,,,EVENTOUT, +PortF,PF1,,,,,I2C2_SCL,,,,,,,,FSMC_A1,,,EVENTOUT, +PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FSMC_A2,,,EVENTOUT, +PortF,PF3,,,TIM5_CH1,,,,,,,,,,FSMC_A3,,,EVENTOUT, +PortF,PF4,,,TIM5_CH2,,,,,,,,,,FSMC_A4,,,EVENTOUT, +PortF,PF5,,,TIM5_CH3,,,,,,,,,,FSMC_A5,,,EVENTOUT, +PortF,PF6,TRACED0,,,TIM10_CH1,,,,SAI1_SD_B,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT, +PortF,PF7,TRACED1,,,TIM11_CH1,,,,SAI1_MCLK_B,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT, +PortF,PF8,,,,,,,,SAI1_SCK_B,UART8_RX,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT, +PortF,PF9,,,,,,,,SAI1_FS_B,UART8_TX,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT, +PortF,PF10,,TIM1_ETR,TIM5_CH4,,,,,,,,,,,,,EVENTOUT, +PortF,PF11,,,,TIM8_ETR,,,,,,,,,,,,EVENTOUT, +PortF,PF12,,,,TIM8_BKIN,,,,,,,,,FSMC_A6,,,EVENTOUT, +PortF,PF13,,,,,I2CFMP1_SMBA,,,,,,,,FSMC_A7,,,EVENTOUT, +PortF,PF14,,,,,I2CFMP1_SCL,,,,,,,,FSMC_A8,,,EVENTOUT, +PortF,PF15,,,,,I2CFMP1_SDA,,,,,,,,FSMC_A9,,,EVENTOUT, +PortG,PG0,,,,,,,,,,CAN1_RX,,UART9_RX,FSMC_A10,,,EVENTOUT, +PortG,PG1,,,,,,,,,,CAN1_TX,,UART9_TX,FSMC_A11,,,EVENTOUT, +PortG,PG2,,,,,,,,,,,,,FSMC_A12,,,EVENTOUT, +PortG,PG3,,,,,,,,,,,,,FSMC_A13,,,EVENTOUT, +PortG,PG4,,,,,,,,,,,,,FSMC_A14,,,EVENTOUT, +PortG,PG5,,,,,,,,,,,,,FSMC_A15,,,EVENTOUT, +PortG,PG6,,,,,,,,,,,QUADSPI_BK1_NCS,,,,,EVENTOUT, +PortG,PG7,,,,,,,,,USART6_CK,,,,,,,EVENTOUT, +PortG,PG8,,,,,,,,,USART6_RTS,,,,,,,EVENTOUT, +PortG,PG9,,,,,,,,,USART6_RX,QUADSPI_BK2_IO2,,,FSMC_NE2,,,EVENTOUT, +PortG,PG10,,,,,,,,,,,,,FSMC_NE3,,,EVENTOUT, +PortG,PG11,,,,,,,,,,CAN2_RX,,UART10_RX,,,,EVENTOUT, +PortG,PG12,,,,,,,,,USART6_RTS,CAN2_TX,,UART10_TX,FSMC_NE4,,,EVENTOUT, +PortG,PG13,TRACED2,,,,,,,,USART6_CTS,,,,FSMC_A24,,,EVENTOUT, +PortG,PG14,TRACED3,,,,,,,,USART6_TX,QUADSPI_BK2_IO3,,,FSMC_A25,,,EVENTOUT, +PortG,PG15,,,,,,,,,USART6_CTS,,,,,,,EVENTOUT, +PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, diff --git a/ports/stm32/boards/stm32f413xg.ld b/ports/stm32/boards/stm32f413xg.ld new file mode 100644 index 0000000000000..cac313bc673ae --- /dev/null +++ b/ports/stm32/boards/stm32f413xg.ld @@ -0,0 +1,31 @@ +/* + GNU linker script for STM32F413xg (1MB flash, 320kB RAM) +*/ + +/* Specify the memory areas */ +/* FLASH_FS2 is placed before FLASH_TEXT to support 1MB and 1.5MB FLASH with common code in flashbdev.c */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* entire flash */ + FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ + FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 176K /* sectors 1,2,3 are 16K, 4 is 64K, 5 is 128K (64K used) for filesystem */ + FLASH_FS2 (rx) : ORIGIN = 0x08040000, LENGTH = 128K /* sector 6 is 128K (64K used) for filesystem, Total filesystem 240K */ + FLASH_TEXT (rx) : ORIGIN = 0x08060000, LENGTH = 640K /* sectors 7,8,9,10,11 are 128K*/ + SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 64K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* Define tho top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _ram_end - 16K; /* 240K, tunable */ diff --git a/ports/stm32/boards/stm32f413xh.ld b/ports/stm32/boards/stm32f413xh.ld new file mode 100644 index 0000000000000..f6dc430e322ff --- /dev/null +++ b/ports/stm32/boards/stm32f413xh.ld @@ -0,0 +1,31 @@ +/* + GNU linker script for STM32F413xh (1.5MB flash, 320kB RAM) +*/ + +/* Specify the memory areas */ +/* FLASH_FS2 is placed before FLASH_TEXT to support 1MB and 1.5MB FLASH with common code in flashbdev.c */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1536K /* entire flash */ + FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */ + FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 176K /* sectors 1,2,3 are 16K, 4 is 64K, 5 is 128K (64K used) for filesystem */ + FLASH_FS2 (rx) : ORIGIN = 0x08040000, LENGTH = 128K /* sector 6 is 128K (64K used) for filesystem, Total filesystem 240K */ + FLASH_TEXT (rx) : ORIGIN = 0x08060000, LENGTH = 1152K /* sectors 7,8,9,10,11,12,13,14,15 are 128K*/ + SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 64K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* Define tho top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _ram_end - 16K; /* 240K, tunable */ diff --git a/ports/stm32/can.c b/ports/stm32/can.c index 2293f94db8818..90a3d79a95233 100644 --- a/ports/stm32/can.c +++ b/ports/stm32/can.c @@ -114,7 +114,7 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) { sce_irq = CAN1_SCE_IRQn; pins[0] = MICROPY_HW_CAN1_TX; pins[1] = MICROPY_HW_CAN1_RX; - __CAN1_CLK_ENABLE(); + __HAL_RCC_CAN1_CLK_ENABLE(); break; #endif @@ -124,8 +124,18 @@ STATIC bool can_init(pyb_can_obj_t *can_obj) { sce_irq = CAN2_SCE_IRQn; pins[0] = MICROPY_HW_CAN2_TX; pins[1] = MICROPY_HW_CAN2_RX; - __CAN1_CLK_ENABLE(); // CAN2 is a "slave" and needs CAN1 enabled as well - __CAN2_CLK_ENABLE(); + __HAL_RCC_CAN1_CLK_ENABLE(); // CAN2 is a "slave" and needs CAN1 enabled as well + __HAL_RCC_CAN2_CLK_ENABLE(); + break; + #endif + + #if defined(MICROPY_HW_CAN3_TX) + case PYB_CAN_3: + CANx = CAN3; + sce_irq = CAN3_SCE_IRQn; + pins[0] = MICROPY_HW_CAN3_TX; + pins[1] = MICROPY_HW_CAN3_RX; + __HAL_RCC_CAN3_CLK_ENABLE(); // CAN3 is a "master" and doesn't need CAN1 enabled as well break; #endif @@ -420,6 +430,10 @@ STATIC mp_obj_t pyb_can_make_new(const mp_obj_type_t *type, size_t n_args, size_ } else if (strcmp(port, MICROPY_HW_CAN2_NAME) == 0) { can_idx = PYB_CAN_2; #endif + #ifdef MICROPY_HW_CAN3_NAME + } else if (strcmp(port, MICROPY_HW_CAN3_NAME) == 0) { + can_idx = PYB_CAN_3; + #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%s) doesn't exist", port)); } @@ -479,17 +493,26 @@ STATIC mp_obj_t pyb_can_deinit(mp_obj_t self_in) { HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn); HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn); HAL_NVIC_DisableIRQ(CAN1_SCE_IRQn); - __CAN1_FORCE_RESET(); - __CAN1_RELEASE_RESET(); - __CAN1_CLK_DISABLE(); + __HAL_RCC_CAN1_FORCE_RESET(); + __HAL_RCC_CAN1_RELEASE_RESET(); + __HAL_RCC_CAN1_CLK_DISABLE(); #if defined(CAN2) } else if (self->can.Instance == CAN2) { HAL_NVIC_DisableIRQ(CAN2_RX0_IRQn); HAL_NVIC_DisableIRQ(CAN2_RX1_IRQn); HAL_NVIC_DisableIRQ(CAN2_SCE_IRQn); - __CAN2_FORCE_RESET(); - __CAN2_RELEASE_RESET(); - __CAN2_CLK_DISABLE(); + __HAL_RCC_CAN2_FORCE_RESET(); + __HAL_RCC_CAN2_RELEASE_RESET(); + __HAL_RCC_CAN2_CLK_DISABLE(); + #endif + #if defined(CAN3) + } else if (self->can.Instance == CAN3) { + HAL_NVIC_DisableIRQ(CAN3_RX0_IRQn); + HAL_NVIC_DisableIRQ(CAN3_RX1_IRQn); + HAL_NVIC_DisableIRQ(CAN3_SCE_IRQn); + __HAL_RCC_CAN3_FORCE_RESET(); + __HAL_RCC_CAN3_RELEASE_RESET(); + __HAL_RCC_CAN3_CLK_DISABLE(); #endif } return mp_const_none; @@ -890,11 +913,15 @@ STATIC mp_obj_t pyb_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_ma if (filter.FilterNumber >= can2_start_bank) { goto error; } - } else { + } else if (self->can_id == 2) { filter.FilterNumber = filter.FilterNumber + can2_start_bank; if (filter.FilterNumber > 27) { goto error; } + } else { + if (filter.FilterNumber > 13) { // CAN3 is independant and has its own 14 filters. + goto error; + } } filter.FilterActivation = ENABLE; filter.BankNumber = can2_start_bank; @@ -930,9 +957,13 @@ STATIC mp_obj_t pyb_can_rxcallback(mp_obj_t self_in, mp_obj_t fifo_in, mp_obj_t if (self->can_id == PYB_CAN_1) { irq = (fifo == 0) ? CAN1_RX0_IRQn : CAN1_RX1_IRQn; #if defined(CAN2) - } else { + } else if (self->can_id == PYB_CAN_2) { irq = (fifo == 0) ? CAN2_RX0_IRQn : CAN2_RX1_IRQn; #endif + #if defined(CAN3) + } else { + irq = (fifo == 0) ? CAN3_RX0_IRQn : CAN3_RX1_IRQn; + #endif } NVIC_SetPriority(irq, IRQ_PRI_CAN); HAL_NVIC_EnableIRQ(irq); diff --git a/ports/stm32/can.h b/ports/stm32/can.h index 54e7deaa5e0f9..ade77acf7ec9f 100644 --- a/ports/stm32/can.h +++ b/ports/stm32/can.h @@ -28,6 +28,7 @@ #define PYB_CAN_1 (1) #define PYB_CAN_2 (2) +#define PYB_CAN_3 (3) extern const mp_obj_type_t pyb_can_type; diff --git a/ports/stm32/flashbdev.c b/ports/stm32/flashbdev.c index 0b95dcc4ffc0c..484fa1a1bc0ab 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -61,6 +61,15 @@ STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k #define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (128) // sectors 1,2,3,4: 16k+16k+16k+16k(of 64k)=64k +#elif defined(STM32F413xx) + +#define CACHE_MEM_START_ADDR (0x10000000) // SRAM2 data RAM, 64k +#define FLASH_SECTOR_SIZE_MAX (0x10000) // 64k max, size of SRAM2 +#define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 +#define FLASH_MEM_SEG1_NUM_BLOCKS (352) // sectors 1,2,3,4,5: 16k+16k+16k+64k+64k(of 128k)=176k +#define FLASH_MEM_SEG2_START_ADDR (0x08040000) // sector 6 +#define FLASH_MEM_SEG2_NUM_BLOCKS (128) // sector 6: 64k(of 128k). Filesystem 176K + 64K = 240K + #elif defined(STM32F429xx) #define CACHE_MEM_START_ADDR (0x10000000) // CCM data RAM, 64k diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index c1e594807146a..169e8c589d14d 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -385,6 +385,14 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size } else if (strcmp(port, MICROPY_HW_UART8_NAME) == 0) { uart_id = PYB_UART_8; #endif + #ifdef MICROPY_HW_UART9_NAME + } else if (strcmp(port, MICROPY_HW_UART9_NAME) == 0) { + uart_id = PYB_UART_9; + #endif + #ifdef MICROPY_HW_UART10_NAME + } else if (strcmp(port, MICROPY_HW_UART10_NAME) == 0) { + uart_id = PYB_UART_10; + #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%s) doesn't exist", port)); } diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 08c835a1c2c43..4348f50bdd51e 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -147,8 +147,14 @@ #define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7a10) #define PYB_EXTI_NUM_VECTORS (23) #define MICROPY_HW_MAX_TIMER (14) -#ifdef UART8 +#if defined(UART10) +#define MICROPY_HW_MAX_UART (10) +#elif defined(UART9) +#define MICROPY_HW_MAX_UART (9) +#elif defined(UART8) #define MICROPY_HW_MAX_UART (8) +#elif defined(UART7) +#define MICROPY_HW_MAX_UART (7) #else #define MICROPY_HW_MAX_UART (6) #endif @@ -239,11 +245,20 @@ #endif // Enable CAN if there are any peripherals defined -#if defined(MICROPY_HW_CAN1_TX) || defined(MICROPY_HW_CAN2_TX) +#if defined(MICROPY_HW_CAN1_TX) || defined(MICROPY_HW_CAN2_TX) || defined(MICROPY_HW_CAN3_TX) #define MICROPY_HW_ENABLE_CAN (1) #else #define MICROPY_HW_ENABLE_CAN (0) +#define MICROPY_HW_MAX_CAN (0) #endif +#if defined(MICROPY_HW_CAN3_TX) +#define MICROPY_HW_MAX_CAN (3) +#elif defined(MICROPY_HW_CAN2_TX) +#define MICROPY_HW_MAX_CAN (2) +#elif defined(MICROPY_HW_CAN1_TX) +#define MICROPY_HW_MAX_CAN (1) +#endif + // Pin definition header file #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h" diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 7cb67a115ac25..5a1687c07ba4d 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -291,7 +291,7 @@ extern const struct _mp_obj_module_t mp_module_onewire; struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART]; \ \ /* pointers to all CAN objects (if they have been created) */ \ - struct _pyb_can_obj_t *pyb_can_obj_all[2]; \ + struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \ \ /* list of registered NICs */ \ mp_obj_list_t mod_network_nic_list; \ diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 637442a9169b1..078b143bbd35d 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -751,6 +751,22 @@ void UART8_IRQHandler(void) { } #endif +#if defined(UART9) +void UART9_IRQHandler(void) { + IRQ_ENTER(UART9_IRQn); + uart_irq_handler(9); + IRQ_EXIT(UART9_IRQn); +} +#endif + +#if defined(UART10) +void UART10_IRQHandler(void) { + IRQ_ENTER(UART10_IRQn); + uart_irq_handler(10); + IRQ_EXIT(UART10_IRQn); +} +#endif + #endif #if defined(MICROPY_HW_CAN1_TX) @@ -793,6 +809,26 @@ void CAN2_SCE_IRQHandler(void) { } #endif +#if defined(MICROPY_HW_CAN3_TX) +void CAN3_RX0_IRQHandler(void) { + IRQ_ENTER(CAN3_RX0_IRQn); + can_rx_irq_handler(PYB_CAN_3, CAN_FIFO0); + IRQ_EXIT(CAN3_RX0_IRQn); +} + +void CAN3_RX1_IRQHandler(void) { + IRQ_ENTER(CAN3_RX1_IRQn); + can_rx_irq_handler(PYB_CAN_3, CAN_FIFO1); + IRQ_EXIT(CAN3_RX1_IRQn); +} + +void CAN3_SCE_IRQHandler(void) { + IRQ_ENTER(CAN3_SCE_IRQn); + can_sce_irq_handler(PYB_CAN_3); + IRQ_EXIT(CAN3_SCE_IRQn); +} +#endif + #if MICROPY_PY_PYB_LEGACY #if defined(MICROPY_HW_I2C1_SCL) diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 4156551038443..317dbe95b6c7c 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -154,6 +154,14 @@ bool uart_exists(int uart_id) { case PYB_UART_8: return true; #endif + #if defined(MICROPY_HW_UART9_TX) && defined(MICROPY_HW_UART9_RX) + case PYB_UART_9: return true; + #endif + + #if defined(MICROPY_HW_UART10_TX) && defined(MICROPY_HW_UART10_RX) + case PYB_UART_10: return true; + #endif + default: return false; } } @@ -318,6 +326,28 @@ bool uart_init(pyb_uart_obj_t *uart_obj, break; #endif + #if defined(MICROPY_HW_UART9_TX) && defined(MICROPY_HW_UART9_RX) + case PYB_UART_9: + uart_unit = 9; + UARTx = UART9; + irqn = UART9_IRQn; + __HAL_RCC_UART9_CLK_ENABLE(); + pins[0] = MICROPY_HW_UART9_TX; + pins[1] = MICROPY_HW_UART9_RX; + break; + #endif + + #if defined(MICROPY_HW_UART10_TX) && defined(MICROPY_HW_UART10_RX) + case PYB_UART_10: + uart_unit = 10; + UARTx = UART10; + irqn = UART10_IRQn; + __HAL_RCC_UART10_CLK_ENABLE(); + pins[0] = MICROPY_HW_UART10_TX; + pins[1] = MICROPY_HW_UART10_RX; + break; + #endif + default: // UART does not exist or is not configured for this board return false; @@ -475,6 +505,20 @@ void uart_deinit(pyb_uart_obj_t *self) { __HAL_RCC_USART8_RELEASE_RESET(); __HAL_RCC_USART8_CLK_DISABLE(); #endif + #if defined(UART9) + } else if (self->uart_id == 9) { + HAL_NVIC_DisableIRQ(UART9_IRQn); + __HAL_RCC_UART9_FORCE_RESET(); + __HAL_RCC_UART9_RELEASE_RESET(); + __HAL_RCC_UART9_CLK_DISABLE(); + #endif + #if defined(UART10) + } else if (self->uart_id == 10) { + HAL_NVIC_DisableIRQ(UART10_IRQn); + __HAL_RCC_UART10_FORCE_RESET(); + __HAL_RCC_UART10_RELEASE_RESET(); + __HAL_RCC_UART10_CLK_DISABLE(); + #endif } } @@ -538,6 +582,12 @@ uint32_t uart_get_baudrate(pyb_uart_obj_t *self) { #if defined(USART6) || self->uart_id == 6 #endif + #if defined(UART9) + || self->uart_id == 9 + #endif + #if defined(UART10) + || self->uart_id == 10 + #endif ) { uart_clk = HAL_RCC_GetPCLK2Freq(); } else { diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index 827b3c12d7d01..9b0d139588129 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -38,6 +38,8 @@ typedef enum { PYB_UART_6 = 6, PYB_UART_7 = 7, PYB_UART_8 = 8, + PYB_UART_9 = 9, + PYB_UART_10 = 10, } pyb_uart_t; #define CHAR_WIDTH_8BIT (0) From 2a791170cea7841b9a7600d371b8c0355a3cc20a Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 19 Apr 2019 15:19:49 +1000 Subject: [PATCH 0048/1299] stm32/boards: Add NUCLEO_F413ZH board configuration. The alternate function pin allocations are different to other NUCLEO-144 boards. This is because the STM32F413 has a very high peripheral count: 10x UART, 5x SPI, 3x I2C, 3x CAN. The pinout was chosen to expose all these devices on separate pins except CAN3 which shares a pin with UART1 and SPI1 which shares pins with DAC. --- .../boards/NUCLEO_F413ZH/mpconfigboard.h | 101 +++++ .../boards/NUCLEO_F413ZH/mpconfigboard.mk | 7 + ports/stm32/boards/NUCLEO_F413ZH/pins.csv | 118 +++++ .../boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h | 409 ++++++++++++++++++ 4 files changed, 635 insertions(+) create mode 100644 ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h create mode 100644 ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk create mode 100644 ports/stm32/boards/NUCLEO_F413ZH/pins.csv create mode 100644 ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h diff --git a/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h new file mode 100644 index 0000000000000..2f488159a4f00 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.h @@ -0,0 +1,101 @@ +#define MICROPY_HW_BOARD_NAME "NUCLEO-F413ZH" +#define MICROPY_HW_MCU_NAME "STM32F413" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) + +// HSE is 8MHz, CPU freq set to 96MHz +#define MICROPY_HW_CLK_PLLM (8) +#define MICROPY_HW_CLK_PLLN (192) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (4) + +// For 2.7 to 3.6 V, 75 to 100 MHz: 3 wait states. +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_3 + +// UART config +#define MICROPY_HW_UART1_TX (pin_B6) +#define MICROPY_HW_UART1_RX (pin_B3) // shared with CAN3 +#define MICROPY_HW_UART2_TX (pin_D5) +#define MICROPY_HW_UART2_RX (pin_D6) +#define MICROPY_HW_UART3_TX (pin_D8) +#define MICROPY_HW_UART3_RX (pin_D9) +#define MICROPY_HW_UART4_TX (pin_D1) +#define MICROPY_HW_UART4_RX (pin_D0) +#define MICROPY_HW_UART5_TX (pin_C12) +#define MICROPY_HW_UART5_RX (pin_D2) +#define MICROPY_HW_UART6_TX (pin_G14) +#define MICROPY_HW_UART6_RX (pin_G9) +#define MICROPY_HW_UART7_TX (pin_E8) +#define MICROPY_HW_UART7_RX (pin_E7) +#define MICROPY_HW_UART8_TX (pin_E1) +#define MICROPY_HW_UART8_RX (pin_E0) +#define MICROPY_HW_UART9_TX (pin_D15) +#define MICROPY_HW_UART9_RX (pin_D14) +#define MICROPY_HW_UART10_TX (pin_E3) +#define MICROPY_HW_UART10_RX (pin_E2) +#define MICROPY_HW_UART_REPL PYB_UART_3 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C busses +#define MICROPY_HW_I2C1_SCL (pin_B8) +#define MICROPY_HW_I2C1_SDA (pin_B9) +#define MICROPY_HW_I2C2_SCL (pin_F1) +#define MICROPY_HW_I2C2_SDA (pin_F0) +#define MICROPY_HW_I2C3_SCL (pin_A8) +#define MICROPY_HW_I2C3_SDA (pin_C9) + +// SPI busses +#define MICROPY_HW_SPI1_NSS (pin_A4) // shared with DAC +#define MICROPY_HW_SPI1_SCK (pin_A5) // shared with DAC +#define MICROPY_HW_SPI1_MISO (pin_A6) +#define MICROPY_HW_SPI1_MOSI (pin_A7) +#define MICROPY_HW_SPI2_NSS (pin_B12) +#define MICROPY_HW_SPI2_SCK (pin_C7) +#define MICROPY_HW_SPI2_MISO (pin_C2) +#define MICROPY_HW_SPI2_MOSI (pin_C3) +#define MICROPY_HW_SPI3_NSS (pin_A15) +#define MICROPY_HW_SPI3_SCK (pin_C10) +#define MICROPY_HW_SPI3_MISO (pin_C11) +#define MICROPY_HW_SPI3_MOSI (pin_B5) +#define MICROPY_HW_SPI4_NSS (pin_E4) +#define MICROPY_HW_SPI4_SCK (pin_B13) +#define MICROPY_HW_SPI4_MISO (pin_E5) +#define MICROPY_HW_SPI4_MOSI (pin_E6) +#define MICROPY_HW_SPI5_NSS (pin_E11) +#define MICROPY_HW_SPI5_SCK (pin_E12) +#define MICROPY_HW_SPI5_MISO (pin_E13) +#define MICROPY_HW_SPI5_MOSI (pin_E14) + +// CAN busses +#define MICROPY_HW_CAN1_TX (pin_G1) +#define MICROPY_HW_CAN1_RX (pin_G0) +#define MICROPY_HW_CAN2_TX (pin_G12) +#define MICROPY_HW_CAN2_RX (pin_G11) +#define MICROPY_HW_CAN3_TX (pin_B4) +#define MICROPY_HW_CAN3_RX (pin_B3) // shared with UART1 or use pin_A8 shared with I2C3 + +// USRSW is pulled low. Pressing the button makes the input go high. +#define MICROPY_HW_USRSW_PIN (pin_C13) +#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) +#define MICROPY_HW_USRSW_PRESSED (1) + +// LEDs +#define MICROPY_HW_LED1 (pin_B14) // red +#define MICROPY_HW_LED2 (pin_B0) // green +#define MICROPY_HW_LED3 (pin_B7) // blue +#define MICROPY_HW_LED1_PWM { TIM12, 12, TIM_CHANNEL_1, GPIO_AF9_TIM12 } +#define MICROPY_HW_LED2_PWM { TIM3, 3, TIM_CHANNEL_3, GPIO_AF2_TIM3 } +#define MICROPY_HW_LED3_PWM { TIM4, 4, TIM_CHANNEL_2, GPIO_AF2_TIM4 } +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// USB config (CN13 - USB OTG FS) +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) +#define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) diff --git a/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk new file mode 100644 index 0000000000000..efc05dba843b5 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk @@ -0,0 +1,7 @@ +MCU_SERIES = f4 +CMSIS_MCU = STM32F413xx +STARTUP_FILE = boards/startup_stm32f413xx.o +AF_FILE = boards/stm32f413_af.csv +LD_FILES = boards/stm32f413xh.ld boards/common_ifs.ld +TEXT0_ADDR = 0x08000000 +TEXT1_ADDR = 0x08060000 diff --git a/ports/stm32/boards/NUCLEO_F413ZH/pins.csv b/ports/stm32/boards/NUCLEO_F413ZH/pins.csv new file mode 100644 index 0000000000000..31dcb99ed616c --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F413ZH/pins.csv @@ -0,0 +1,118 @@ +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +PA8,PA8 +PA9,PA9 +PA10,PA10 +PA11,PA11 +PA12,PA12 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PB0,PB0 +PB1,PB1 +PB2,PB2 +PB3,PB3 +PB4,PB4 +PB5,PB5 +PB6,PB6 +PB7,PB7 +PB8,PB8 +PB9,PB9 +PB10,PB10 +PB11,PB11 +PB12,PB12 +PB13,PB13 +PB14,PB14 +PB15,PB15 +PC0,PC0 +PC1,PC1 +PC2,PC2 +PC3,PC3 +PC4,PC4 +PC5,PC5 +PC6,PC6 +PC7,PC7 +PC8,PC8 +PC9,PC9 +PC10,PC10 +PC11,PC11 +PC12,PC12 +PC13,PC13 +PC14,PC14 +PC15,PC15 +PD0,PD0 +PD1,PD1 +PD2,PD2 +PD3,PD3 +PD4,PD4 +PD5,PD5 +PD6,PD6 +PD7,PD7 +PD8,PD8 +PD9,PD9 +PD10,PD10 +PD11,PD11 +PD12,PD12 +PD13,PD13 +PD14,PD14 +PD15,PD15 +PE0,PE0 +PE1,PE1 +PE2,PE2 +PE3,PE3 +PE4,PE4 +PE5,PE5 +PE6,PE6 +PE7,PE7 +PE8,PE8 +PE9,PE9 +PE10,PE10 +PE11,PE11 +PE12,PE12 +PE13,PE13 +PE14,PE14 +PE15,PE15 +PF0,PF0 +PF1,PF1 +PF2,PF2 +PF3,PF3 +PF4,PF4 +PF5,PF5 +PF6,PF6 +PF7,PF7 +PF8,PF8 +PF9,PF9 +PF10,PF10 +PF11,PF11 +PF12,PF12 +PF13,PF13 +PF14,PF14 +PF15,PF15 +PG0,PG0 +PG1,PG1 +PG2,PG2 +PG3,PG3 +PG4,PG4 +PG5,PG5 +PG6,PG6 +PG7,PG7 +PG8,PG8 +PG9,PG9 +PG10,PG10 +PG11,PG11 +PG12,PG12 +PG13,PG13 +PG14,PG14 +PG15,PG15 +PH0,PH0 +PH1,PH1 +SW,C13 +LED_RED,B14 +LED_GREEN,B0 +LED_BLUE,B7 diff --git a/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h new file mode 100644 index 0000000000000..5b5a8a3e43e52 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h @@ -0,0 +1,409 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_conf.h + * @author MCD Application Team + * @version V1.1.0 + * @date 19-June-2014 + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + + /* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +#define HAL_DAC_MODULE_ENABLED +/* #define HAL_DCMI_MODULE_ENABLED */ +#define HAL_DMA_MODULE_ENABLED +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +#define HAL_FLASH_MODULE_ENABLED +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCCARD_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +/* #define HAL_SAI_MODULE_ENABLED */ +#define HAL_SD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +/* #define HAL_HCD_MODULE_ENABLED */ + + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)40000) +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ +#define USE_RTOS 0 +#define PREFETCH_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define DATA_CACHE_ENABLE 1 + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1 */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2 +#define MAC_ADDR1 0 +#define MAC_ADDR2 0 +#define MAC_ADDR3 0 +#define MAC_ADDR4 0 +#define MAC_ADDR5 0 + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848 PHY Address*/ +#define DP83848_PHY_ADDRESS 0x01 +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FF) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) + +#define PHY_READ_TO ((uint32_t)0x0000FFFF) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ + +#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ +#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ +#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ + +#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ + +#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ +#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ + +#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ +#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 9a6f6fd68d2563e0115b11c01c322aaa14a107bb Mon Sep 17 00:00:00 2001 From: Nguyen Hoan Hoang Date: Wed, 20 Mar 2019 17:38:03 +0700 Subject: [PATCH 0049/1299] nrf/boards: Add support for BLYST Nano module based boards. - IBK-BLYST-NANO: Breakout board - IDK-BLYST-NANO: DevKit board with builtin IDAP-M CMSIS-DAP Debug JTAG, RGB led - BLUEIO-TAG-EVIM: Sensor tag board (environmental sensor (T, H, P, Air quality) + 9 axis motion sensor) Also, the LED module has been updated to support individual base level configuration of each LED. If set, this will be used instead of the common configuration, MICROPY_HW_LED_PULLUP. The new configuration, MICROPY_HW_LEDX_LEVEL, where X is the LED number can be used to set the base level of the specific LED. --- ports/nrf/Makefile | 8 ++ ports/nrf/README.md | 14 ++ .../boards/blueio_tag_evim/mpconfigboard.h | 77 +++++++++++ .../boards/blueio_tag_evim/mpconfigboard.mk | 8 ++ ports/nrf/boards/blueio_tag_evim/pins.csv | 30 +++++ .../nrf/boards/ibk_blyst_nano/mpconfigboard.h | 69 ++++++++++ .../boards/ibk_blyst_nano/mpconfigboard.mk | 8 ++ ports/nrf/boards/ibk_blyst_nano/pins.csv | 30 +++++ .../nrf/boards/idk_blyst_nano/mpconfigboard.h | 70 ++++++++++ .../boards/idk_blyst_nano/mpconfigboard.mk | 8 ++ ports/nrf/boards/idk_blyst_nano/pins.csv | 30 +++++ ports/nrf/modules/board/led.c | 126 +++++++++++++++--- ports/nrf/modules/board/led.h | 4 + 13 files changed, 465 insertions(+), 17 deletions(-) create mode 100644 ports/nrf/boards/blueio_tag_evim/mpconfigboard.h create mode 100644 ports/nrf/boards/blueio_tag_evim/mpconfigboard.mk create mode 100644 ports/nrf/boards/blueio_tag_evim/pins.csv create mode 100644 ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h create mode 100644 ports/nrf/boards/ibk_blyst_nano/mpconfigboard.mk create mode 100644 ports/nrf/boards/ibk_blyst_nano/pins.csv create mode 100644 ports/nrf/boards/idk_blyst_nano/mpconfigboard.h create mode 100644 ports/nrf/boards/idk_blyst_nano/mpconfigboard.mk create mode 100644 ports/nrf/boards/idk_blyst_nano/pins.csv diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 80110f9704ddf..cc7b4f1260b77 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -296,6 +296,14 @@ sd: $(BUILD)/$(OUTPUT_FILENAME).hex pyocd-flashtool -t $(MCU_VARIANT) $(SOFTDEV_HEX) pyocd-flashtool -t $(MCU_VARIANT) $< +else ifeq ($(FLASHER), idap) + +flash: $(BUILD)/$(OUTPUT_FILENAME).hex + IDAPnRFPRog $< + +sd: $(BUILD)/$(OUTPUT_FILENAME).hex + IDAPnRFPRog $(SOFTDEV_HEX) $< + endif $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) diff --git a/ports/nrf/README.md b/ports/nrf/README.md index 659a556ae2b26..2a1667a3eb2a0 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -34,6 +34,8 @@ This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. * [Adafruit Feather nRF52](https://www.adafruit.com/product/3406) * [Thingy:52](http://www.nordicsemi.com/eng/Products/Nordic-Thingy-52) * [Arduino Primo](http://www.arduino.org/products/boards/arduino-primo) + * [IBK-BLYST-NANO breakout board](https://www.crowdsupply.com/i-syst/blyst-nano) + * [BLUEIO-TAG-EVIM BLYST Nano Sensor board](https://www.crowdsupply.com/i-syst/blyst-nano) * nRF52840 * [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK) @@ -120,8 +122,20 @@ wt51822_s4at | s110 | Peripheral | Manual pca10040 | s132 | Peripheral and Central | [Segger](#segger-targets) feather52 | s132 | Peripheral and Central | Manual, SWDIO and SWCLK solder points on the bottom side of the board arduino_primo | s132 | Peripheral and Central | [PyOCD](#pyocdopenocd-targets) +ibk_blyst_nano | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) +idk_blyst_nano | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) +blueio_tag_evim | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) pca10056 | s140 | Peripheral and Central | [Segger](#segger-targets) +## IDAP-M/IDAP-Link Targets + +Install the necessary tools to flash and debug using IDAP-M/IDAP-Link CMSIS-DAP Debug JTAG: + +[IDAPnRFProg for Linux](https://sourceforge.net/projects/idaplinkfirmware/files/Linux/IDAPnRFProg_1_7_190320.zip/download) +[IDAPnRFProg for OSX](https://sourceforge.net/projects/idaplinkfirmware/files/OSX/IDAPnRFProg_1_7_190320.zip/download) +[IDAPnRFProg for Windows](https://sourceforge.net/projects/idaplinkfirmware/files/Windows/IDAPnRFProg_1_7_190320.zip/download) + + ## Segger Targets Install the necessary tools to flash and debug using Segger: diff --git a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h new file mode 100644 index 0000000000000..afc3f00a81fa7 --- /dev/null +++ b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h @@ -0,0 +1,77 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 I-SYST inc. + * + * 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. + */ + +#define MICROPY_HW_BOARD_NAME "BLUEIO-TAG-EVIM" +#define MICROPY_HW_MCU_NAME "NRF52832" +#define MICROPY_PY_SYS_PLATFORM "BLYST Nano" + +#define MICROPY_PY_MACHINE_SOFT_PWM (1) +#define MICROPY_PY_MUSIC (1) + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_PWM (1) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_RTCOUNTER (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_TEMP (1) +#define MICROPY_PY_RANDOM_HW_RNG (1) + +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_LED_COUNT (4) +#define MICROPY_HW_LED_PULLUP (1) + +#define MICROPY_HW_LED1 (30) // LED1 +#define MICROPY_HW_LED1_LEVEL (0) +#define MICROPY_HW_LED2 (20) // LED2 +#define MICROPY_HW_LED2_LEVEL (1) +#define MICROPY_HW_LED3 (19) // LED3 +#define MICROPY_HW_LED3_LEVEL (1) +#define MICROPY_HW_LED4 (18) // LED4 +#define MICROPY_HW_LED4_LEVEL (1) + +// UART config +#define MICROPY_HW_UART1_RX (8) +#define MICROPY_HW_UART1_TX (7) +#define MICROPY_HW_UART1_CTS (12) +#define MICROPY_HW_UART1_RTS (11) +#define MICROPY_HW_UART1_HWFC (1) + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (23) // +#define MICROPY_HW_SPI0_MOSI (24) // +#define MICROPY_HW_SPI0_MISO (25) // + +#define MICROPY_HW_PWM0_NAME "PWM0" +#define MICROPY_HW_PWM1_NAME "PWM1" +#define MICROPY_HW_PWM2_NAME "PWM2" + +// buzzer pin +#define MICROPY_HW_MUSIC_PIN (14) + +#define HELP_TEXT_BOARD_LED "1,2,3,4" diff --git a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.mk b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.mk new file mode 100644 index 0000000000000..02a3177446b10 --- /dev/null +++ b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.mk @@ -0,0 +1,8 @@ +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52832 +SOFTDEV_VERSION = 6.1.1 +LD_FILES += boards/nrf52832_512k_64k.ld +FLASHER = idap + +NRF_DEFINES += -DNRF52832_XXAA diff --git a/ports/nrf/boards/blueio_tag_evim/pins.csv b/ports/nrf/boards/blueio_tag_evim/pins.csv new file mode 100644 index 0000000000000..90bf84a04d44a --- /dev/null +++ b/ports/nrf/boards/blueio_tag_evim/pins.csv @@ -0,0 +1,30 @@ +P2,P2 +P3,P3 +P4,P4 +P5,P5 +P6,P6 +P7,P7 +P8,P8 +P9,P9 +P10,P10 +P11,P11 +P12,P12 +P13,P13 +P14,P14 +P15,P15 +P16,P16 +P17,P17 +P18,P18 +P19,P19 +P20,P20 +P21,P21 +P22,P22 +P23,P23 +P24,P24 +P25,P25 +P26,P26 +P27,P27 +P28,P28 +P29,P29 +P30,P30 +P31,P31 diff --git a/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h b/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h new file mode 100644 index 0000000000000..11b8c28e38df8 --- /dev/null +++ b/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h @@ -0,0 +1,69 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 I-SYST inc. + * + * 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. + */ + +#define MICROPY_HW_BOARD_NAME "IBK-BLYST-NANO" +#define MICROPY_HW_MCU_NAME "NRF52832" +#define MICROPY_PY_SYS_PLATFORM "BLYST Nano" + +#define MICROPY_PY_MACHINE_SOFT_PWM (1) +#define MICROPY_PY_MUSIC (1) + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_PWM (1) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_RTCOUNTER (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_TEMP (1) +#define MICROPY_PY_RANDOM_HW_RNG (1) + +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_LED_COUNT (3) +#define MICROPY_HW_LED_PULLUP (1) + +#define MICROPY_HW_LED1 (30) // LED1 +#define MICROPY_HW_LED2 (29) // LED2 +#define MICROPY_HW_LED3 (28) // LED3 + +// UART config +#define MICROPY_HW_UART1_RX (8) +#define MICROPY_HW_UART1_TX (7) +#define MICROPY_HW_UART1_CTS (12) +#define MICROPY_HW_UART1_RTS (11) +#define MICROPY_HW_UART1_HWFC (1) + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (23) // +#define MICROPY_HW_SPI0_MOSI (24) // +#define MICROPY_HW_SPI0_MISO (25) // + +#define MICROPY_HW_PWM0_NAME "PWM0" +#define MICROPY_HW_PWM1_NAME "PWM1" +#define MICROPY_HW_PWM2_NAME "PWM2" + +#define HELP_TEXT_BOARD_LED "1,2,3" diff --git a/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.mk b/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.mk new file mode 100644 index 0000000000000..02a3177446b10 --- /dev/null +++ b/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.mk @@ -0,0 +1,8 @@ +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52832 +SOFTDEV_VERSION = 6.1.1 +LD_FILES += boards/nrf52832_512k_64k.ld +FLASHER = idap + +NRF_DEFINES += -DNRF52832_XXAA diff --git a/ports/nrf/boards/ibk_blyst_nano/pins.csv b/ports/nrf/boards/ibk_blyst_nano/pins.csv new file mode 100644 index 0000000000000..90bf84a04d44a --- /dev/null +++ b/ports/nrf/boards/ibk_blyst_nano/pins.csv @@ -0,0 +1,30 @@ +P2,P2 +P3,P3 +P4,P4 +P5,P5 +P6,P6 +P7,P7 +P8,P8 +P9,P9 +P10,P10 +P11,P11 +P12,P12 +P13,P13 +P14,P14 +P15,P15 +P16,P16 +P17,P17 +P18,P18 +P19,P19 +P20,P20 +P21,P21 +P22,P22 +P23,P23 +P24,P24 +P25,P25 +P26,P26 +P27,P27 +P28,P28 +P29,P29 +P30,P30 +P31,P31 diff --git a/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h b/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h new file mode 100644 index 0000000000000..1d39ad7569740 --- /dev/null +++ b/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h @@ -0,0 +1,70 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 I-SYST inc. + * + * 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. + */ + +#define MICROPY_HW_BOARD_NAME "IDK-BLYST-NANO" +#define MICROPY_HW_MCU_NAME "NRF52832" +#define MICROPY_PY_SYS_PLATFORM "BLYST Nano" + +#define MICROPY_PY_MACHINE_SOFT_PWM (1) +#define MICROPY_PY_MUSIC (1) + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_PWM (1) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_RTCOUNTER (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_TEMP (1) +#define MICROPY_PY_RANDOM_HW_RNG (1) + +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_LED_COUNT (4) +#define MICROPY_HW_LED_PULLUP (1) + +#define MICROPY_HW_LED1 (30) // LED1 +#define MICROPY_HW_LED2 (29) // LED2 +#define MICROPY_HW_LED3 (28) // LED3 +#define MICROPY_HW_LED4 (27) // LED4 + +// UART config +#define MICROPY_HW_UART1_RX (8) +#define MICROPY_HW_UART1_TX (7) +#define MICROPY_HW_UART1_CTS (12) +#define MICROPY_HW_UART1_RTS (11) +#define MICROPY_HW_UART1_HWFC (1) + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (23) // +#define MICROPY_HW_SPI0_MOSI (24) // +#define MICROPY_HW_SPI0_MISO (25) // + +#define MICROPY_HW_PWM0_NAME "PWM0" +#define MICROPY_HW_PWM1_NAME "PWM1" +#define MICROPY_HW_PWM2_NAME "PWM2" + +#define HELP_TEXT_BOARD_LED "1,2,3,4" diff --git a/ports/nrf/boards/idk_blyst_nano/mpconfigboard.mk b/ports/nrf/boards/idk_blyst_nano/mpconfigboard.mk new file mode 100644 index 0000000000000..02a3177446b10 --- /dev/null +++ b/ports/nrf/boards/idk_blyst_nano/mpconfigboard.mk @@ -0,0 +1,8 @@ +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52832 +SOFTDEV_VERSION = 6.1.1 +LD_FILES += boards/nrf52832_512k_64k.ld +FLASHER = idap + +NRF_DEFINES += -DNRF52832_XXAA diff --git a/ports/nrf/boards/idk_blyst_nano/pins.csv b/ports/nrf/boards/idk_blyst_nano/pins.csv new file mode 100644 index 0000000000000..90bf84a04d44a --- /dev/null +++ b/ports/nrf/boards/idk_blyst_nano/pins.csv @@ -0,0 +1,30 @@ +P2,P2 +P3,P3 +P4,P4 +P5,P5 +P6,P6 +P7,P7 +P8,P8 +P9,P9 +P10,P10 +P11,P11 +P12,P12 +P13,P13 +P14,P14 +P15,P15 +P16,P16 +P17,P17 +P18,P18 +P19,P19 +P20,P20 +P21,P21 +P22,P22 +P23,P23 +P24,P24 +P25,P25 +P26,P26 +P27,P27 +P28,P28 +P29,P29 +P30,P30 +P31,P31 diff --git a/ports/nrf/modules/board/led.c b/ports/nrf/modules/board/led.c index 687348cb86809..8b1eb560eadf4 100644 --- a/ports/nrf/modules/board/led.c +++ b/ports/nrf/modules/board/led.c @@ -33,31 +33,122 @@ #if MICROPY_HW_HAS_LED -#define LED_OFF(pin) {(MICROPY_HW_LED_PULLUP) ? nrf_gpio_pin_set(pin) : nrf_gpio_pin_clear(pin); } -#define LED_ON(pin) {(MICROPY_HW_LED_PULLUP) ? nrf_gpio_pin_clear(pin) : nrf_gpio_pin_set(pin); } - typedef struct _board_led_obj_t { mp_obj_base_t base; mp_uint_t led_id; mp_uint_t hw_pin; uint8_t hw_pin_port; + bool act_level; } board_led_obj_t; -STATIC const board_led_obj_t board_led_obj[] = { +static inline void LED_OFF(board_led_obj_t * const led_obj) { + if (led_obj->act_level) { + nrf_gpio_pin_clear(led_obj->hw_pin); + } + else { + nrf_gpio_pin_set(led_obj->hw_pin); + } +} + +static inline void LED_ON(board_led_obj_t * const led_obj) { + if (led_obj->act_level) { + nrf_gpio_pin_set(led_obj->hw_pin); + } + else { + nrf_gpio_pin_clear(led_obj->hw_pin); + } +} + + +static const board_led_obj_t board_led_obj[] = { + #if MICROPY_HW_LED_TRICOLOR - {{&board_led_type}, BOARD_LED_RED, MICROPY_HW_LED_RED}, - {{&board_led_type}, BOARD_LED_GREEN, MICROPY_HW_LED_GREEN}, - {{&board_led_type}, BOARD_LED_BLUE, MICROPY_HW_LED_BLUE}, + + {{&board_led_type}, BOARD_LED_RED, MICROPY_HW_LED_RED, 0, MICROPY_HW_LED_PULLUP != 0 ? 0 : 1}, + {{&board_led_type}, BOARD_LED_GREEN, MICROPY_HW_LED_GREEN,0, MICROPY_HW_LED_PULLUP != 0 ? 0 : 1}, + {{&board_led_type}, BOARD_LED_BLUE, MICROPY_HW_LED_BLUE,0, MICROPY_HW_LED_PULLUP != 0 ? 0 : 1}, + #elif (MICROPY_HW_LED_COUNT == 1) - {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1}, + + {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, + #ifdef MICROPY_HW_LED1_LEVEL + MICROPY_HW_LED1_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + #elif (MICROPY_HW_LED_COUNT == 2) - {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1}, - {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2}, + + {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, + #ifdef MICROPY_HW_LED1_LEVEL + MICROPY_HW_LED1_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2, 0, + #ifdef MICROPY_HW_LED2_LEVEL + MICROPY_HW_LED2_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + +#elif (MICROPY_HW_LED_COUNT == 3) + + {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, + #ifdef MICROPY_HW_LED1_LEVEL + MICROPY_HW_LED1_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2, 0, + #ifdef MICROPY_HW_LED2_LEVEL + MICROPY_HW_LED2_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + {{&board_led_type}, BOARD_LED3, MICROPY_HW_LED3, 0, + #ifdef MICROPY_HW_LED3_LEVEL + MICROPY_HW_LED3_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + #else - {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1}, - {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2}, - {{&board_led_type}, BOARD_LED3, MICROPY_HW_LED3}, - {{&board_led_type}, BOARD_LED4, MICROPY_HW_LED4}, + + {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, + #ifdef MICROPY_HW_LED1_LEVEL + MICROPY_HW_LED1_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2, 0, + #ifdef MICROPY_HW_LED2_LEVEL + MICROPY_HW_LED2_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + {{&board_led_type}, BOARD_LED3, MICROPY_HW_LED3, 0, + #ifdef MICROPY_HW_LED3_LEVEL + MICROPY_HW_LED3_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, + {{&board_led_type}, BOARD_LED4, MICROPY_HW_LED4, 0, + #ifdef MICROPY_HW_LED4_LEVEL + MICROPY_HW_LED4_LEVEL, + #else + MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + #endif + }, #endif }; @@ -65,16 +156,17 @@ STATIC const board_led_obj_t board_led_obj[] = { void led_init(void) { for (uint8_t i = 0; i < NUM_LEDS; i++) { - LED_OFF(board_led_obj[i].hw_pin); + LED_OFF((board_led_obj_t*)&board_led_obj[i]); nrf_gpio_cfg_output(board_led_obj[i].hw_pin); } } void led_state(board_led_obj_t * led_obj, int state) { if (state == 1) { - LED_ON(led_obj->hw_pin); + LED_ON(led_obj); + } else { - LED_OFF(led_obj->hw_pin); + LED_OFF(led_obj); } } diff --git a/ports/nrf/modules/board/led.h b/ports/nrf/modules/board/led.h index 6210039f498d3..537b9ac546ad3 100644 --- a/ports/nrf/modules/board/led.h +++ b/ports/nrf/modules/board/led.h @@ -38,6 +38,10 @@ typedef enum { #elif (MICROPY_HW_LED_COUNT == 2) BOARD_LED1 = 1, BOARD_LED2 = 2, +#elif (MICROPY_HW_LED_COUNT == 3) + BOARD_LED1 = 1, + BOARD_LED2 = 2, + BOARD_LED3 = 3, #else BOARD_LED1 = 1, BOARD_LED2 = 2, From 5ea38e4d7485aca5ce4e74bff1785c0d8e41fa1c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 May 2019 23:18:30 +1000 Subject: [PATCH 0050/1299] py/native: Improve support for bool type in viper functions. Variables with type bool now act more like an int, and there is proper casting to/from Python objects. --- py/emitnative.c | 2 +- py/nativeglue.c | 2 +- tests/micropython/viper_types.py | 26 ++++++++++++++++++++++++++ tests/micropython/viper_types.py.exp | 8 ++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/micropython/viper_types.py create mode 100644 tests/micropython/viper_types.py.exp diff --git a/py/emitnative.c b/py/emitnative.c index da986dc5d96a1..cb6cc94d35a58 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1356,7 +1356,7 @@ STATIC void emit_native_load_global(emit_t *emit, qstr qst, int kind) { if (emit->do_viper_types) { // check for builtin casting operators int native_type = mp_native_type_from_qstr(qst); - if (native_type >= MP_NATIVE_TYPE_INT) { + if (native_type >= MP_NATIVE_TYPE_BOOL) { emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, native_type); return; } diff --git a/py/nativeglue.c b/py/nativeglue.c index db54d12332931..c810f31e60f25 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -60,7 +60,7 @@ mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type) { DEBUG_printf("mp_native_from_obj(%p, " UINT_FMT ")\n", obj, type); switch (type & 0xf) { case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; - case MP_NATIVE_TYPE_BOOL: + case MP_NATIVE_TYPE_BOOL: return mp_obj_is_true(obj); case MP_NATIVE_TYPE_INT: case MP_NATIVE_TYPE_UINT: return mp_obj_get_int_truncated(obj); default: { // cast obj to a pointer diff --git a/tests/micropython/viper_types.py b/tests/micropython/viper_types.py new file mode 100644 index 0000000000000..ae72c0cf30285 --- /dev/null +++ b/tests/micropython/viper_types.py @@ -0,0 +1,26 @@ +# test various type conversions + +import micropython + +# converting incoming arg to bool +@micropython.viper +def f1(x:bool): + print(x) +f1(0) +f1(1) +f1([]) +f1([1]) + +# taking and returning a bool +@micropython.viper +def f2(x:bool) -> bool: + return x +print(f2([])) +print(f2([1])) + +# converting to bool within function +@micropython.viper +def f3(x) -> bool: + return bool(x) +print(f3([])) +print(f3(-1)) diff --git a/tests/micropython/viper_types.py.exp b/tests/micropython/viper_types.py.exp new file mode 100644 index 0000000000000..b7bef156ea494 --- /dev/null +++ b/tests/micropython/viper_types.py.exp @@ -0,0 +1,8 @@ +False +True +False +True +False +True +False +True From c2bb4519085fff1a30605e3f672635c21a747ed8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 May 2019 23:21:08 +1000 Subject: [PATCH 0051/1299] tests/basics/sys1.py: Add test for calling sys.exit() without any args. --- tests/basics/sys1.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/basics/sys1.py b/tests/basics/sys1.py index 0d74a1292b180..30e36f81a8d9a 100644 --- a/tests/basics/sys1.py +++ b/tests/basics/sys1.py @@ -24,6 +24,11 @@ except SystemExit as e: print("SystemExit", e.args) +try: + sys.exit() +except SystemExit as e: + print("SystemExit", e.args) + try: sys.exit(42) except SystemExit as e: From 906fb89fd778cb695ba81c871086fe1ce340e681 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 May 2019 23:21:28 +1000 Subject: [PATCH 0052/1299] unix/coverage: Add test for printing literal % character. --- ports/unix/coverage.c | 1 + tests/unix/extra_coverage.py.exp | 1 + 2 files changed, 2 insertions(+) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 3c121a153836d..538c32d614a19 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -161,6 +161,7 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier + mp_printf(&mp_plat_print, "%%\n"); // literal % character } // GC diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 2e23b24585c7c..6c483f7e547c5 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -13,6 +13,7 @@ false true 80000000 80000000 abc +% # GC 0 0 From ef9843653b795b650e1fe77e22f87e3523bd0a08 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 23 Apr 2019 12:39:05 +0300 Subject: [PATCH 0053/1299] extmod/moducryptolib: Add AES-CTR support. Selectable at compile time via MICROPY_PY_UCRYPTOLIB_CTR. Disabled by default. --- docs/library/ucryptolib.rst | 4 +- extmod/moducryptolib.c | 99 ++++++++++++++++++----- ports/unix/mpconfigport_coverage.h | 1 + py/mpconfig.h | 5 ++ tests/extmod/ucryptolib_aes128_ctr.py | 28 +++++++ tests/extmod/ucryptolib_aes128_ctr.py.exp | 3 + 6 files changed, 119 insertions(+), 21 deletions(-) create mode 100644 tests/extmod/ucryptolib_aes128_ctr.py create mode 100644 tests/extmod/ucryptolib_aes128_ctr.py.exp diff --git a/docs/library/ucryptolib.rst b/docs/library/ucryptolib.rst index c9e0bb71f7ae0..79471c2e90ccc 100644 --- a/docs/library/ucryptolib.rst +++ b/docs/library/ucryptolib.rst @@ -22,9 +22,11 @@ Classes * *mode* is: * ``1`` (or ``ucryptolib.MODE_ECB`` if it exists) for Electronic Code Book (ECB). - * ``2`` (or ``ucryptolib.MODE_CBC`` if it exists) for Cipher Block Chaining (CBC) + * ``2`` (or ``ucryptolib.MODE_CBC`` if it exists) for Cipher Block Chaining (CBC). + * ``6`` (or ``ucryptolib.MODE_CTR`` if it exists) for Counter mode (CTR). * *IV* is an initialization vector for CBC mode. + * For Counter mode, *IV* is the initial value for the counter. .. method:: encrypt(in_buf, [out_buf]) diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c index af9eec624e98d..6c45c2fdef92f 100644 --- a/extmod/moducryptolib.c +++ b/extmod/moducryptolib.c @@ -41,10 +41,17 @@ // values follow PEP 272 enum { - UCRYPTOLIB_MODE_MIN = 0, - UCRYPTOLIB_MODE_ECB, - UCRYPTOLIB_MODE_CBC, - UCRYPTOLIB_MODE_MAX, + UCRYPTOLIB_MODE_ECB = 1, + UCRYPTOLIB_MODE_CBC = 2, + UCRYPTOLIB_MODE_CTR = 6, +}; + +struct ctr_params { + // counter is the IV of the AES context. + + size_t offset; // in encrypted_counter + // encrypted counter + uint8_t encrypted_counter[16]; }; #if MICROPY_SSL_AXTLS @@ -82,6 +89,19 @@ typedef struct _mp_obj_aes_t { uint8_t key_type: 2; } mp_obj_aes_t; +STATIC inline bool is_ctr_mode(int block_mode) { + #if MICROPY_PY_UCRYPTOLIB_CTR + return block_mode == UCRYPTOLIB_MODE_CTR; + #else + return false; + #endif +} + +STATIC inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) { + // ctr_params follows aes object struct + return (struct ctr_params*)&o[1]; +} + #if MICROPY_SSL_AXTLS STATIC void aes_initial_set_key_impl(AES_CTX_IMPL *ctx, const uint8_t *key, size_t keysize, const uint8_t iv[16]) { assert(16 == keysize || 32 == keysize); @@ -155,20 +175,38 @@ STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_ STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, bool encrypt) { mbedtls_aes_crypt_cbc(&ctx->u.mbedtls_ctx, encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT, in_len, ctx->iv, in, out); } + +#if MICROPY_PY_UCRYPTOLIB_CTR +STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) { + mbedtls_aes_crypt_ctr(&ctx->u.mbedtls_ctx, in_len, &ctr_params->offset, ctx->iv, ctr_params->encrypted_counter, in, out); +} +#endif + #endif STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 3, false); - mp_obj_aes_t *o = m_new_obj(mp_obj_aes_t); - o->base.type = type; - o->block_mode = mp_obj_get_int(args[1]); - o->key_type = AES_KEYTYPE_NONE; + const mp_int_t block_mode = mp_obj_get_int(args[1]); + + switch (block_mode) { + case UCRYPTOLIB_MODE_ECB: + case UCRYPTOLIB_MODE_CBC: + #if MICROPY_PY_UCRYPTOLIB_CTR + case UCRYPTOLIB_MODE_CTR: + #endif + break; - if (o->block_mode <= UCRYPTOLIB_MODE_MIN || o->block_mode >= UCRYPTOLIB_MODE_MAX) { - mp_raise_ValueError("mode"); + default: + mp_raise_ValueError("mode"); } + mp_obj_aes_t *o = m_new_obj_var(mp_obj_aes_t, struct ctr_params, !!is_ctr_mode(block_mode)); + o->base.type = type; + + o->block_mode = block_mode; + o->key_type = AES_KEYTYPE_NONE; + mp_buffer_info_t keyinfo; mp_get_buffer_raise(args[0], &keyinfo, MP_BUFFER_READ); if (32 != keyinfo.len && 16 != keyinfo.len) { @@ -183,10 +221,14 @@ STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args if (16 != ivinfo.len) { mp_raise_ValueError("IV"); } - } else if (o->block_mode == UCRYPTOLIB_MODE_CBC) { + } else if (o->block_mode == UCRYPTOLIB_MODE_CBC || is_ctr_mode(o->block_mode)) { mp_raise_ValueError("IV"); } + if (is_ctr_mode(block_mode)) { + ctr_params_from_aes(o)->offset = 0; + } + aes_initial_set_key_impl(&o->ctx, keyinfo.buf, keyinfo.len, ivinfo.buf); return MP_OBJ_FROM_PTR(o); @@ -204,7 +246,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) { mp_buffer_info_t in_bufinfo; mp_get_buffer_raise(in_buf, &in_bufinfo, MP_BUFFER_READ); - if (in_bufinfo.len % 16 != 0) { + if (!is_ctr_mode(self->block_mode) && in_bufinfo.len % 16 != 0) { mp_raise_ValueError("blksize % 16"); } @@ -224,7 +266,9 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) { } if (AES_KEYTYPE_NONE == self->key_type) { - aes_final_set_key_impl(&self->ctx, encrypt); + // always set key for encryption if CTR mode. + const bool encrypt_mode = encrypt || is_ctr_mode(self->block_mode); + aes_final_set_key_impl(&self->ctx, encrypt_mode); self->key_type = encrypt ? AES_KEYTYPE_ENC : AES_KEYTYPE_DEC; } else { if ((encrypt && self->key_type == AES_KEYTYPE_DEC) || @@ -234,14 +278,26 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) { } } - if (self->block_mode == UCRYPTOLIB_MODE_ECB) { - uint8_t *in = in_bufinfo.buf, *out = out_buf_ptr; - uint8_t *top = in + in_bufinfo.len; - for (; in < top; in += 16, out += 16) { - aes_process_ecb_impl(&self->ctx, in, out, encrypt); + switch (self->block_mode) { + case UCRYPTOLIB_MODE_ECB: { + uint8_t *in = in_bufinfo.buf, *out = out_buf_ptr; + uint8_t *top = in + in_bufinfo.len; + for (; in < top; in += 16, out += 16) { + aes_process_ecb_impl(&self->ctx, in, out, encrypt); + } + break; } - } else { - aes_process_cbc_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len, encrypt); + + case UCRYPTOLIB_MODE_CBC: + aes_process_cbc_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len, encrypt); + break; + + #if MICROPY_PY_UCRYPTOLIB_CTR + case UCRYPTOLIB_MODE_CTR: + aes_process_ctr_impl(&self->ctx, in_bufinfo.buf, out_buf_ptr, in_bufinfo.len, + ctr_params_from_aes(self)); + break; + #endif } if (out_buf != MP_OBJ_NULL) { @@ -279,6 +335,9 @@ STATIC const mp_rom_map_elem_t mp_module_ucryptolib_globals_table[] = { #if MICROPY_PY_UCRYPTOLIB_CONSTS { MP_ROM_QSTR(MP_QSTR_MODE_ECB), MP_ROM_INT(UCRYPTOLIB_MODE_ECB) }, { MP_ROM_QSTR(MP_QSTR_MODE_CBC), MP_ROM_INT(UCRYPTOLIB_MODE_CBC) }, + #if MICROPY_PY_UCRYPTOLIB_CTR + { MP_ROM_QSTR(MP_QSTR_MODE_CTR), MP_ROM_INT(UCRYPTOLIB_MODE_CTR) }, + #endif #endif }; diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index 87bf8454cec19..f3fbee6bfa8af 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -58,6 +58,7 @@ #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1) #define MICROPY_PY_UCRYPTOLIB (1) +#define MICROPY_PY_UCRYPTOLIB_CTR (1) // TODO these should be generic, not bound to fatfs #define mp_type_fileio mp_type_vfs_posix_fileio diff --git a/py/mpconfig.h b/py/mpconfig.h index 893ac7dc7eddb..38b36a4b18762 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1281,6 +1281,11 @@ typedef double mp_float_t; #define MICROPY_PY_UCRYPTOLIB (0) #endif +// Depends on MICROPY_PY_UCRYPTOLIB +#ifndef MICROPY_PY_UCRYPTOLIB_CTR +#define MICROPY_PY_UCRYPTOLIB_CTR (0) +#endif + #ifndef MICROPY_PY_UCRYPTOLIB_CONSTS #define MICROPY_PY_UCRYPTOLIB_CONSTS (0) #endif diff --git a/tests/extmod/ucryptolib_aes128_ctr.py b/tests/extmod/ucryptolib_aes128_ctr.py new file mode 100644 index 0000000000000..5a16b452977ee --- /dev/null +++ b/tests/extmod/ucryptolib_aes128_ctr.py @@ -0,0 +1,28 @@ +try: + from ucryptolib import aes +except ImportError: + print("SKIP") + raise SystemExit + + +def _new(k, ctr_initial): + return aes(k, 6, ctr_initial) + + +try: + _new(b'x' * 16, b'x' * 16) +except ValueError as e: + # is CTR support disabled? + if e.args[0] == "mode": + print("SKIP") + raise SystemExit + raise e + +crypto = _new(b"1234" * 4, b"5678" * 4) +enc = crypto.encrypt(b'a') +print(enc) +enc += crypto.encrypt(b'b' * 1000) +print(enc) + +crypto = _new(b"1234" * 4, b"5678" * 4) +print(crypto.decrypt(enc)) diff --git a/tests/extmod/ucryptolib_aes128_ctr.py.exp b/tests/extmod/ucryptolib_aes128_ctr.py.exp new file mode 100644 index 0000000000000..92e090fd39700 --- /dev/null +++ b/tests/extmod/ucryptolib_aes128_ctr.py.exp @@ -0,0 +1,3 @@ +b'\x06' +b'\x06(F\x08\xc3hB\xfdO\x05;\xf6\x96\xfe\xad\xe0\xca\xe6\xd1\xa2m\t\x91v>|\xee\xe0q\xbc]\x9a`\xfal\x87\xa6e\xfb\x8a\xf4\xb2-\xc4x,\xfc@=,\x90\xf4\xe9h\xf0\xfc\xfb\xe6\x03\xf0d\xb6\xcdObZ\xde\x1b\xe2\x84-%=\xa9\xe4\x05\xab\xd7\x044\xf4$\xd0)\xfd\xd6\xdbL\xdd\xe6\x0cp\xca^p\xaaA\x8b\xb3!\xe3\x13\xfa\x7f#\xfa0\xbd\x0b\x9cX\xec\xed\x1c\xbc\x06\xa4\xa8\x17\xbfg\x98dW\xb9~\x04\xec\xe6lZ\xb0\xab\xd5\xc6v\xe4\x8f\x98G\xff\x9b\x8a\xae\xfd\xe5\xed\x96\x1b\xe2\x99u3\xeb\x9faYr;\xf0g\xf2\x9cq\x8dI\x1cL\xc9\xa8\xb0\xdeD\xd5\x06\x87u=\xcd\x10\x1c\xab\x14\x06n\x99\x13\x89\x9f5\xea\xd2\x08\x9e\xef$?\xb9\xdeQ\x0b\x90CH\xea@V\x94\x1a\xdd\x7f\x1dz\x82\xaay\xea$Lv\x07\x8e\xce\xb8oN\x15\xf8,\x05\x00\xd9H\xf4\xbe\xb8\xee\x0e\xd6Hjh\xc6\x11\xf8:\xfe\xed\xba_\xaf\x8e\'\x0c\x7fZ\xd5\xb7\xbc\xba\xd3+\xf1\x98i\xab\x0c-\xd9\xe6>\x9e\xd0\xe6>\x9f\xebn\xf0\x15\xd9:\xec\xf7aXa\xb2,CAB7\x18g\xcc#\xbc\xb8\xf9\xa7\xf4V\xba\x0baN\x88\xb1\xea\x94\x05\x0cV\x99_\xc4\xe6\xb2\xd1|\x92\x05*@U\xe4\\\x8dR\x98\xdf\xbfS\x97\x12^\tr\x1f\x12\x8f\xdfi\x8e=\xc4I\xfcB\r\x99f\xe3\xe31\xee\xa9\xcd\x91\x1a\x1ei\xfd\xf4\x84\xc6\xda\x9e\xf3\x8aKn\xaa\xf7\x9eS\xcc\xbaXZ\x0cpbk\x18\x1f\x9aAl>y\xad\xcb\xcf\xe1Wm\xe7\xdd\xcc\x10eW\xe4h\x1dY\xb5Zs\xf1\xe7\x16_\xdc:I1R\xd3\xfe\xb1)\t\xddE\xbax\x06R\xdc\x1dSdlu\xd1\x9c\x00\xaf\x87\x8d1\xbf$\x08\xc6/y\xdf\x1f\x97z(\xff\xb9\xcb\xf2,\x91\xd7\xa0W\xfc\xe3\xe2\x905\x17O\xaf\x18\xc7\xb8?\x94^\xf5@\x80\x8d\xaa*p\xbeR0i\x17\x1e\'-\xfa\xd9\xb2\x03\xb8\x1fY\x13\xc1{\x7f\xa9\x86\t\x99\xee\xa2\xba\xab\xc1\xbb\x07a\xa5J\x01\x98\xe8\x8e\xa1\x8aV\xc1)^A\xd9\xe7\xfej`\xb4\xe9\xd3C\xab\xd4\xdb\xb1\x8c\x83\xaa&\xf1\xe2\xfc\xa1Lb\xa8\xbb\xd6\x83\xb7\xd8\xc5\x9e\xb5\xed\x1b\xe6\x91\x90\xe4\xfa\xfdD\xc2\xcb\xb7U\xb3|?(\x86=\xc2\xff\xd3P\xd2\xc5y\x93\x13r\xcd>5\x80\xde\xdaJ\xdd\x8b\xfa\x14\xd1\x85\xa8P\x06(F\xb3?\xefm\x8e\xe5C\xfe\x98\xaf\xed\xd1!(\x1f.\xc6M\xba\x00\xcb\xbfg5\xc8\x9d\x97+\x14\x87\xf5\x9d4\xb4l\xd5\xc5>\x90\xf2\x06\xa2\xc1R\x89\xf0P\xb4\xe5\x97\xdb\x07\xd3\xc6q\x08\xb9\xe7\r\xf9\x13\x8215\xcb\x92\xed\x99\xc7"\x1e\xe3Zsh\x0e\xe7\xae\x10Xs&)\x1d\xe5\xd5\xbc\x95\x8e\xa3\xd6k[k\x9c\xa0%\xd4\x83%\x88}\x90\xf0\xa7\xc7\xa4(\xdaE\xb9~\xae\x05\xbd}\xe2\xd0\xa5Y\xc1aV[\xab\x93S\xa6\xacg\r\x14\xc6\xe2J\xd6\xcck"\xcc\xfb\xb3\x97\x14\x13\x0b\xd1\xf5\xe7)_\x1e\x0b\xbb\x01\xf7\x11u\x85b\xdf\xab\xe3\xbb:\x84zF\x14u\xfe\x89\x90\xbc\xcaF\x15y\xa3\xa4[\xce\xcf-\xae\x18\x97N\xaa\xed\x84A\xfc\x9e\xeb\xb3\xfcH\x8ej\xcc\x9f \x1b\xc1\x1f}\'q.\xc0^\xd99\x1e\x91b-\xf9\xed\xfd\x9a\x7f\xb6\rO\xea\xc8\x94\xea\xf6\xb4\xdb\xf5\xc7\xb3\xef\xf6D\x12>5\xf3\x9d*\xc9\xf8\x9f]\xb01{d\xe7\'\x8f\xc0\xfbKB\x8dd\xb1\x84\x804\xbe\xe2?AT\x14\xdb4eJ\x96\xc5\xb9%\xe5\x1c\xc0L\xae\xd6O\xde\x1fjJIRD\x96\xa2\xdb\xfc\xc6t\xce\xe6\xe8"\x81\xe6\xc7\x7fuz\xb3\x91\'D\xac\xb2\x93O\xee\x14\xaa7yT\xcf\x81p\x0b(\xa1d\xda\xf8\xcb\x01\x98\x07\'\xfe/\xe4\xca\xab\x03uR"zY\xfb\x1f\x02\xc5\x9c\xa0\'\x89\xffO\x88cK\xac\xb1+S0]%E\x1a\xeb\x04\xf7\x0b\xba\xa0\xbb\xbd|\x06@T\xee\xe7\x17\xa1T\xe3"\x07\x07q' +b'abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' From 32ba679924b8f5c8a81cff905e6bd295c6bb4df8 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sun, 28 Apr 2019 23:57:11 +0300 Subject: [PATCH 0054/1299] extmod/moducryptolib: Add AES-CTR support for axTLS builds. --- extmod/moducryptolib.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c index 6c45c2fdef92f..15cd4535f8fe6 100644 --- a/extmod/moducryptolib.c +++ b/extmod/moducryptolib.c @@ -139,6 +139,33 @@ STATIC void aes_process_cbc_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t * AES_cbc_decrypt(ctx, in, out, in_len); } } + +#if MICROPY_PY_UCRYPTOLIB_CTR +// axTLS doesn't have CTR support out of the box. This implements the counter part using the ECB primitive. +STATIC void aes_process_ctr_impl(AES_CTX_IMPL *ctx, const uint8_t *in, uint8_t *out, size_t in_len, struct ctr_params *ctr_params) { + size_t n = ctr_params->offset; + uint8_t *const counter = ctx->iv; + + while (in_len--) { + if (n == 0) { + aes_process_ecb_impl(ctx, counter, ctr_params->encrypted_counter, true); + + // increment the 128-bit counter + for (int i = 15; i >= 0; --i) { + if (++counter[i] != 0) { + break; + } + } + } + + *out++ = *in++ ^ ctr_params->encrypted_counter[n]; + n = (n + 1) & 0xf; + } + + ctr_params->offset = n; +} +#endif + #endif #if MICROPY_SSL_MBEDTLS From 089c9b71d10bd66549858254cc10803cba45453a Mon Sep 17 00:00:00 2001 From: Jun Wu Date: Sat, 4 May 2019 20:29:43 -0700 Subject: [PATCH 0055/1299] py: remove "if (0)" and "if (false)" branches. Prior to this commit, building the unix port with `DEBUG=1` and `-finstrument-functions` the compilation would fail with an error like "control reaches end of non-void function". This change fixes this by removing the problematic "if (0)" branches. Not all branches affect compilation, but they are all removed for consistency. --- py/compile.c | 15 ++++++--------- py/emitnative.c | 7 +++---- py/objarray.c | 13 ++++++------- py/objfun.c | 6 +++--- py/objint_mpz.c | 6 +++--- py/runtime.c | 7 +++---- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/py/compile.c b/py/compile.c index 01e4ff9b650a2..27b706c8fe044 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3457,12 +3457,12 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f #endif uint max_num_labels = 0; for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) { - if (false) { #if MICROPY_EMIT_INLINE_ASM - } else if (s->emit_options == MP_EMIT_OPT_ASM) { + if (s->emit_options == MP_EMIT_OPT_ASM) { compile_scope_inline_asm(comp, s, MP_PASS_SCOPE); + } else #endif - } else { + { compile_scope(comp, s, MP_PASS_SCOPE); // Check if any implicitly declared variables should be closed over @@ -3493,11 +3493,8 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f emit_t *emit_native = NULL; #endif for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) { - if (false) { - // dummy - #if MICROPY_EMIT_INLINE_ASM - } else if (s->emit_options == MP_EMIT_OPT_ASM) { + if (s->emit_options == MP_EMIT_OPT_ASM) { // inline assembly if (comp->emit_inline_asm == NULL) { comp->emit_inline_asm = ASM_EMITTER(new)(max_num_labels); @@ -3519,9 +3516,9 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f if (comp->compile_error == MP_OBJ_NULL) { compile_scope_inline_asm(comp, s, MP_PASS_EMIT); } + } else #endif - - } else { + { // choose the emit type diff --git a/py/emitnative.c b/py/emitnative.c index cb6cc94d35a58..f123ecbb58b01 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -2227,17 +2227,16 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { int reg_rhs = REG_ARG_3; emit_pre_pop_reg_flexible(emit, &vtype_rhs, ®_rhs, REG_RET, REG_ARG_2); emit_pre_pop_reg(emit, &vtype_lhs, REG_ARG_2); - if (0) { - // dummy #if !(N_X64 || N_X86) - } else if (op == MP_BINARY_OP_LSHIFT) { + if (op == MP_BINARY_OP_LSHIFT) { ASM_LSL_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_RSHIFT) { ASM_ASR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); + } else #endif - } else if (op == MP_BINARY_OP_OR) { + if (op == MP_BINARY_OP_OR) { ASM_OR_REG_REG(emit->as, REG_ARG_2, reg_rhs); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); } else if (op == MP_BINARY_OP_XOR) { diff --git a/py/objarray.c b/py/objarray.c index 4a8d0af3cc944..02f6dff528fc3 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -375,9 +375,8 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value return MP_OBJ_NULL; // op not supported } else { mp_obj_array_t *o = MP_OBJ_TO_PTR(self_in); - if (0) { #if MICROPY_PY_BUILTINS_SLICE - } else if (mp_obj_is_type(index_in, &mp_type_slice)) { + if (mp_obj_is_type(index_in, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) { mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported"); @@ -456,22 +455,22 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value mp_obj_array_t *res; size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); assert(sz > 0); - if (0) { - // dummy #if MICROPY_PY_BUILTINS_MEMORYVIEW - } else if (o->base.type == &mp_type_memoryview) { + if (o->base.type == &mp_type_memoryview) { res = m_new_obj(mp_obj_array_t); *res = *o; res->memview_offset += slice.start; res->len = slice.stop - slice.start; + } else #endif - } else { + { res = array_new(o->typecode, slice.stop - slice.start); memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz); } return MP_OBJ_FROM_PTR(res); + } else #endif - } else { + { size_t index = mp_get_index(o->base.type, o->len, index_in, false); #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { diff --git a/py/objfun.c b/py/objfun.c index d50b7fa25dc84..d96c79ede4998 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -458,13 +458,13 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { return (mp_uint_t)mp_obj_str_get_data(obj, &l); } else { mp_obj_type_t *type = mp_obj_get_type(obj); - if (0) { #if MICROPY_PY_BUILTINS_FLOAT - } else if (type == &mp_type_float) { + if (type == &mp_type_float) { // convert float to int (could also pass in float registers) return (mp_int_t)mp_obj_float_get(obj); + } else #endif - } else if (type == &mp_type_tuple || type == &mp_type_list) { + if (type == &mp_type_tuple || type == &mp_type_list) { // pointer to start of tuple (could pass length, but then could use len(x) for that) size_t len; mp_obj_t *items; diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 288e9f86d696b..121fd03424893 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -194,18 +194,18 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in); } - if (0) { #if MICROPY_PY_BUILTINS_FLOAT - } else if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) { + if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) { if (mpz_is_zero(zrhs)) { goto zero_division_error; } mp_float_t flhs = mpz_as_float(zlhs); mp_float_t frhs = mpz_as_float(zrhs); return mp_obj_new_float(flhs / frhs); + } else #endif - } else if (op >= MP_BINARY_OP_INPLACE_OR && op < MP_BINARY_OP_CONTAINS) { + if (op >= MP_BINARY_OP_INPLACE_OR && op < MP_BINARY_OP_CONTAINS) { mp_obj_int_t *res = mp_obj_int_new_mpz(); switch (op) { diff --git a/py/runtime.c b/py/runtime.c index a3628eecb45a2..e502566059c02 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1049,14 +1049,13 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { mp_obj_type_t *type = mp_obj_get_type(obj); // look for built-in names - if (0) { #if MICROPY_CPYTHON_COMPAT - } else if (attr == MP_QSTR___class__) { + if (attr == MP_QSTR___class__) { // a.__class__ is equivalent to type(a) dest[0] = MP_OBJ_FROM_PTR(type); + } else #endif - - } else if (attr == MP_QSTR___next__ && type->iternext != NULL) { + if (attr == MP_QSTR___next__ && type->iternext != NULL) { dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj); dest[1] = obj; From 6323cbda4fd82f2396a19e18a224a2579a392303 Mon Sep 17 00:00:00 2001 From: Mike Causer Date: Tue, 12 Feb 2019 23:28:49 +1100 Subject: [PATCH 0056/1299] docs/esp8266: Add tutorial for APA102 LEDs. --- docs/esp8266/tutorial/apa102.rst | 91 ++++++++++++++++++++++++++++++++ docs/esp8266/tutorial/index.rst | 1 + 2 files changed, 92 insertions(+) create mode 100644 docs/esp8266/tutorial/apa102.rst diff --git a/docs/esp8266/tutorial/apa102.rst b/docs/esp8266/tutorial/apa102.rst new file mode 100644 index 0000000000000..1c775daae30ce --- /dev/null +++ b/docs/esp8266/tutorial/apa102.rst @@ -0,0 +1,91 @@ +Controlling APA102 LEDs +======================= + +APA102 LEDs, also known as DotStar LEDs, are individually addressable +full-colour RGB LEDs, generally in a string formation. They differ from +NeoPixels in that they require two pins to control - both a Clock and Data pin. +They can operate at a much higher data and PWM frequencies than NeoPixels and +are more suitable for persistence-of-vision effects. + +To create an APA102 object do the following:: + + >>> import machine, apa102 + >>> strip = apa102.APA102(machine.Pin(5), machine.Pin(4), 60) + +This configures an 60 pixel APA102 strip with clock on GPIO5 and data on GPIO4. +You can adjust the pin numbers and the number of pixels to suit your needs. + +The RGB colour data, as well as a brightness level, is sent to the APA102 in a +certain order. Usually this is ``(Red, Green, Blue, Brightness)``. +If you are using one of the newer APA102C LEDs the green and blue are swapped, +so the order is ``(Red, Blue, Green, Brightness)``. +The APA102 has more of a square lens while the APA102C has more of a round one. +If you are using a APA102C strip and would prefer to provide colours in RGB +order instead of RBG, you can customise the tuple colour order like so:: + + >>> strip.ORDER = (0, 2, 1, 3) + +To set the colour of pixels use:: + + >>> strip[0] = (255, 255, 255, 31) # set to white, full brightness + >>> strip[1] = (255, 0, 0, 31) # set to red, full brightness + >>> strip[2] = (0, 255, 0, 15) # set to green, half brightness + >>> strip[3] = (0, 0, 255, 7) # set to blue, quarter brightness + +Use the ``write()`` method to output the colours to the LEDs:: + + >>> strip.write() + +Demonstration:: + + import time + import machine, apa102 + + # 1M strip with 60 LEDs + strip = apa102.APA102(machine.Pin(5), machine.Pin(4), 60) + + brightness = 1 # 0 is off, 1 is dim, 31 is max + + # Helper for converting 0-255 offset to a colour tuple + def wheel(offset, brightness): + # The colours are a transition r - g - b - back to r + offset = 255 - offset + if offset < 85: + return (255 - offset * 3, 0, offset * 3, brightness) + if offset < 170: + offset -= 85 + return (0, offset * 3, 255 - offset * 3, brightness) + offset -= 170 + return (offset * 3, 255 - offset * 3, 0, brightness) + + # Demo 1: RGB RGB RGB + red = 0xff0000 + green = red >> 8 + blue = red >> 16 + for i in range(strip.n): + colour = red >> (i % 3) * 8 + strip[i] = ((colour & red) >> 16, (colour & green) >> 8, (colour & blue), brightness) + strip.write() + + # Demo 2: Show all colours of the rainbow + for i in range(strip.n): + strip[i] = wheel((i * 256 // strip.n) % 255, brightness) + strip.write() + + # Demo 3: Fade all pixels together through rainbow colours, offset each pixel + for r in range(5): + for n in range(256): + for i in range(strip.n): + strip[i] = wheel(((i * 256 // strip.n) + n) & 255, brightness) + strip.write() + time.sleep_ms(25) + + # Demo 4: Same colour, different brightness levels + for b in range(31,-1,-1): + strip[0] = (255, 153, 0, b) + strip.write() + time.sleep_ms(250) + + # End: Turn off all the LEDs + strip.fill((0, 0, 0, 0)) + strip.write() diff --git a/docs/esp8266/tutorial/index.rst b/docs/esp8266/tutorial/index.rst index 0a4b5f2a6688a..4ba211a4b2d8b 100644 --- a/docs/esp8266/tutorial/index.rst +++ b/docs/esp8266/tutorial/index.rst @@ -29,5 +29,6 @@ to ``__. powerctrl.rst onewire.rst neopixel.rst + apa102.rst dht.rst nextsteps.rst From 7e90e22ea52665e38138d1e704d5e527439b663c Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 2 May 2019 09:59:21 +1000 Subject: [PATCH 0057/1299] mpy-cross: Add --version command line option to print version info. Prints something like: MicroPython v1.10-304-g8031b7a25 on 2019-05-02; mpy-cross emitting mpy v4 --- mpy-cross/main.c | 6 ++++++ py/persistentcode.c | 3 --- py/persistentcode.h | 3 +++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 7bf207596241a..970ad2d75ff0c 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -34,6 +34,7 @@ #include "py/runtime.h" #include "py/gc.h" #include "py/stackctrl.h" +#include "genhdr/mpversion.h" #ifdef _WIN32 #include "ports/windows/fmode.h" #endif @@ -98,6 +99,7 @@ STATIC int usage(char **argv) { printf( "usage: %s [] [-X ] \n" "Options:\n" +"--version : show version information\n" "-o : output file for compiled bytecode (defaults to input with .mpy extension)\n" "-s : source filename to embed in the compiled bytecode (defaults to input file)\n" "-v : verbose (trace various operations); can be multiple\n" @@ -211,6 +213,10 @@ MP_NOINLINE int main_(int argc, char **argv) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-X") == 0) { a += 1; + } else if (strcmp(argv[a], "--version") == 0) { + printf("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE + "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "\n"); + return 0; } else if (strcmp(argv[a], "-v") == 0) { mp_verbose_flag++; } else if (strncmp(argv[a], "-O", 2) == 0) { diff --git a/py/persistentcode.c b/py/persistentcode.c index 70ec2ddd6553d..c8d3bb8a6620c 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -40,9 +40,6 @@ #define QSTR_LAST_STATIC MP_QSTR_zip -// The current version of .mpy files -#define MPY_VERSION (4) - // Macros to encode/decode flags to/from the feature byte #define MPY_FEATURE_ENCODE_FLAGS(flags) (flags) #define MPY_FEATURE_DECODE_FLAGS(feat) ((feat) & 3) diff --git a/py/persistentcode.h b/py/persistentcode.h index b27c3de2f046a..2074c64fe2e05 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -30,6 +30,9 @@ #include "py/reader.h" #include "py/emitglue.h" +// The current version of .mpy files +#define MPY_VERSION 4 + enum { MP_NATIVE_ARCH_NONE = 0, MP_NATIVE_ARCH_X86, From 34942d0a72980173eca51b201f271f67bcae46b5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 2 May 2019 22:04:55 +1000 Subject: [PATCH 0058/1299] stm32/machine_uart: Change default UART timeout to 0, for non blocking. It's more common to need non-blocking behaviour when reading from a UART, rather than having a large timeout like 1000ms (the original behaviour). With a large timeout it's 1) likely that the function will read forever if characters keep trickling it; or 2) the function will unnecessarily wait when characters come sporadically, eg at a REPL prompt. --- docs/library/pyb.UART.rst | 2 +- ports/stm32/machine_uart.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst index 4359f1d9d67c0..ab7ab2fb882a4 100644 --- a/docs/library/pyb.UART.rst +++ b/docs/library/pyb.UART.rst @@ -69,7 +69,7 @@ Constructors Methods ------- -.. method:: UART.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, flow=0, timeout_char=0, read_buf_len=64) +.. method:: UART.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=0, flow=0, timeout_char=0, read_buf_len=64) Initialise the UART bus with the given parameters: diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 169e8c589d14d..29369c0c1411b 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -224,7 +224,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_HWCONTROL_NONE} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, // legacy From 97753a1bbc5a20003bcf2a7f90cff2ca5c81ee92 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 6 May 2019 15:46:52 +1000 Subject: [PATCH 0059/1299] stm32: Move factory reset files and code to separate source file. The new function factory_reset_make_files() populates the given filesystem with the default factory files. It is defined with weak linkage so it can be overridden by a board. This commit also brings some minor user-facing changes: - boot.py is now no longer created unconditionally if it doesn't exist, it is now only created when the filesystem is formatted and the other files are populated (so, before, if the user deleted boot.py it would be recreated at next boot; now it won't be). - pybcdc.inf and README.txt are only created if the board has USB, because they only really make sense if the filesystem is exposed via USB. --- ports/stm32/Makefile | 1 + ports/stm32/factoryreset.c | 98 ++++++++++++++++++++++++++++++++++++++ ports/stm32/factoryreset.h | 33 +++++++++++++ ports/stm32/main.c | 78 ++---------------------------- 4 files changed, 135 insertions(+), 75 deletions(-) create mode 100644 ports/stm32/factoryreset.c create mode 100644 ports/stm32/factoryreset.h diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index d90a7c2e4f2db..943acd4943fbc 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -229,6 +229,7 @@ SRC_C = \ systick.c \ powerctrl.c \ pybthread.c \ + factoryreset.c \ timer.c \ led.c \ pin.c \ diff --git a/ports/stm32/factoryreset.c b/ports/stm32/factoryreset.c new file mode 100644 index 0000000000000..6b0c289a789b6 --- /dev/null +++ b/ports/stm32/factoryreset.c @@ -0,0 +1,98 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "factoryreset.h" + +#if MICROPY_HW_ENABLE_STORAGE + +static const char fresh_boot_py[] = +"# boot.py -- run on boot-up\r\n" +"# can run arbitrary Python, but best to keep it minimal\r\n" +"\r\n" +"import machine\r\n" +"import pyb\r\n" +"#pyb.main('main.py') # main script to run after this one\r\n" +#if MICROPY_HW_ENABLE_USB +"#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n" +"#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n" +#endif +; + +static const char fresh_main_py[] = +"# main.py -- put your code here!\r\n" +; + +#if MICROPY_HW_ENABLE_USB +static const char fresh_pybcdc_inf[] = +#include "genhdr/pybcdc_inf.h" +; + +static const char fresh_readme_txt[] = +"This is a MicroPython board\r\n" +"\r\n" +"You can get started right away by writing your Python code in 'main.py'.\r\n" +"\r\n" +"For a serial prompt:\r\n" +" - Windows: you need to go to 'Device manager', right click on the unknown device,\r\n" +" then update the driver software, using the 'pybcdc.inf' file found on this drive.\r\n" +" Then use a terminal program like Hyperterminal or putty.\r\n" +" - Mac OS X: use the command: screen /dev/tty.usbmodem*\r\n" +" - Linux: use the command: screen /dev/ttyACM0\r\n" +"\r\n" +"Please visit http://micropython.org/help/ for further help.\r\n" +; +#endif + +typedef struct _factory_file_t { + const char *name; + size_t len; + const char *data; +} factory_file_t; + +static const factory_file_t factory_files[] = { + {"boot.py", sizeof(fresh_boot_py) - 1, fresh_boot_py}, + {"main.py", sizeof(fresh_main_py) - 1, fresh_main_py}, + #if MICROPY_HW_ENABLE_USB + {"pybcdc.inf", sizeof(fresh_pybcdc_inf) - 1, fresh_pybcdc_inf}, + {"README.txt", sizeof(fresh_readme_txt) - 1, fresh_readme_txt}, + #endif +}; + +MP_WEAK void factory_reset_make_files(FATFS *fatfs) { + for (int i = 0; i < MP_ARRAY_SIZE(factory_files); ++i) { + const factory_file_t *f = &factory_files[i]; + FIL fp; + FRESULT res = f_open(fatfs, &fp, f->name, FA_WRITE | FA_CREATE_ALWAYS); + if (res == FR_OK) { + UINT n; + f_write(&fp, f->data, f->len, &n); + f_close(&fp); + } + } +} + +#endif // MICROPY_HW_ENABLE_STORAGE diff --git a/ports/stm32/factoryreset.h b/ports/stm32/factoryreset.h new file mode 100644 index 0000000000000..85226f880bdb7 --- /dev/null +++ b/ports/stm32/factoryreset.h @@ -0,0 +1,33 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_FACTORYRESET_H +#define MICROPY_INCLUDED_STM32_FACTORYRESET_H + +#include "lib/oofatfs/ff.h" + +void factory_reset_make_files(FATFS *fatfs); + +#endif // MICROPY_INCLUDED_STM32_FACTORYRESET_H diff --git a/ports/stm32/main.c b/ports/stm32/main.c index a37c6f89790e0..ff4589f9d4a08 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -45,6 +45,7 @@ #include "pendsv.h" #include "pybthread.h" #include "gccollect.h" +#include "factoryreset.h" #include "modmachine.h" #include "i2c.h" #include "spi.h" @@ -148,42 +149,6 @@ STATIC mp_obj_t pyb_main(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a MP_DEFINE_CONST_FUN_OBJ_KW(pyb_main_obj, 1, pyb_main); #if MICROPY_HW_ENABLE_STORAGE -static const char fresh_boot_py[] = -"# boot.py -- run on boot-up\r\n" -"# can run arbitrary Python, but best to keep it minimal\r\n" -"\r\n" -"import machine\r\n" -"import pyb\r\n" -"#pyb.main('main.py') # main script to run after this one\r\n" -#if MICROPY_HW_ENABLE_USB -"#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n" -"#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n" -#endif -; - -static const char fresh_main_py[] = -"# main.py -- put your code here!\r\n" -; - -static const char fresh_pybcdc_inf[] = -#include "genhdr/pybcdc_inf.h" -; - -static const char fresh_readme_txt[] = -"This is a MicroPython board\r\n" -"\r\n" -"You can get started right away by writing your Python code in 'main.py'.\r\n" -"\r\n" -"For a serial prompt:\r\n" -" - Windows: you need to go to 'Device manager', right click on the unknown device,\r\n" -" then update the driver software, using the 'pybcdc.inf' file found on this drive.\r\n" -" Then use a terminal program like Hyperterminal or putty.\r\n" -" - Mac OS X: use the command: screen /dev/tty.usbmodem*\r\n" -" - Linux: use the command: screen /dev/ttyACM0\r\n" -"\r\n" -"Please visit http://micropython.org/help/ for further help.\r\n" -; - // avoid inlining to avoid stack usage within main() MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // init the vfs object @@ -213,23 +178,8 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // set label f_setlabel(&vfs_fat->fatfs, MICROPY_HW_FLASH_FS_LABEL); - // create empty main.py - FIL fp; - f_open(&vfs_fat->fatfs, &fp, "/main.py", FA_WRITE | FA_CREATE_ALWAYS); - UINT n; - f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n); - // TODO check we could write n bytes - f_close(&fp); - - // create .inf driver file - f_open(&vfs_fat->fatfs, &fp, "/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS); - f_write(&fp, fresh_pybcdc_inf, sizeof(fresh_pybcdc_inf) - 1 /* don't count null terminator */, &n); - f_close(&fp); - - // create readme file - f_open(&vfs_fat->fatfs, &fp, "/README.txt", FA_WRITE | FA_CREATE_ALWAYS); - f_write(&fp, fresh_readme_txt, sizeof(fresh_readme_txt) - 1 /* don't count null terminator */, &n); - f_close(&fp); + // populate the filesystem with factory files + factory_reset_make_files(&vfs_fat->fatfs); // keep LED on for at least 200ms systick_wait_at_least(start_tick, 200); @@ -258,28 +208,6 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // It is set to the internal flash filesystem by default. MP_STATE_PORT(vfs_cur) = vfs; - // Make sure we have a /flash/boot.py. Create it if needed. - FILINFO fno; - res = f_stat(&vfs_fat->fatfs, "/boot.py", &fno); - if (res != FR_OK) { - // doesn't exist, create fresh file - - // LED on to indicate creation of boot.py - led_state(PYB_LED_GREEN, 1); - uint32_t start_tick = HAL_GetTick(); - - FIL fp; - f_open(&vfs_fat->fatfs, &fp, "/boot.py", FA_WRITE | FA_CREATE_ALWAYS); - UINT n; - f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); - // TODO check we could write n bytes - f_close(&fp); - - // keep LED on for at least 200ms - systick_wait_at_least(start_tick, 200); - led_state(PYB_LED_GREEN, 0); - } - return true; } #endif From b8c74014e42331afca3db5911b30032a109f73f1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 12:45:24 +1000 Subject: [PATCH 0060/1299] stm32/usbd_cdc_interface: Don't retransmit chars if USB is reconnected. Before this change, if the USB was reconnected it was possible that some characters in the TX buffer were retransmitted because tx_buf_ptr_out and tx_buf_ptr_out_shadow were reset while tx_buf_ptr_in wasn't. That behaviour is fixed here by retaining the TX buffer state across reconnects. Fixes issue #4761. --- ports/stm32/usb.c | 2 +- ports/stm32/usbd_cdc_interface.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 18841fdee4015..8b7608a150231 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -69,7 +69,7 @@ typedef struct _usb_device_t { usbd_hid_itf_t usbd_hid_itf; } usb_device_t; -usb_device_t usb_device; +usb_device_t usb_device = {0}; pyb_usb_storage_medium_t pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_NONE; // predefined hid mouse data diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index 586f2d525e007..4a4a8beb8500e 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -64,14 +64,14 @@ static uint8_t usbd_cdc_connect_tx_timer; uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in; - // Reset all the CDC state - // Note: we don't reset tx_buf_ptr_in in order to allow the output buffer to - // be filled (by usbd_cdc_tx_always) before the USB device is connected. + // Reset the CDC state due to a new USB host connection + // Note: we don't reset tx_buf_ptr_* in order to allow the output buffer to + // be filled (by usbd_cdc_tx_always) before the USB device is connected, and + // to retain transmit buffer state across multiple USB connections (they will + // be 0 at MCU reset since the variables live in the BSS). cdc->rx_buf_put = 0; cdc->rx_buf_get = 0; cdc->rx_buf_full = false; - cdc->tx_buf_ptr_out = 0; - cdc->tx_buf_ptr_out_shadow = 0; cdc->tx_need_empty_packet = 0; cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED; From 3f54462adddb3210b46f3dba3f1879cd01e2f16e Mon Sep 17 00:00:00 2001 From: Elad Namdar Date: Tue, 7 May 2019 00:24:22 +0300 Subject: [PATCH 0061/1299] unix/modusocket: Fix use of setsockopt in usocket.settimeout impl. The original code called setsockopt(SO_RCVTIMEO/SO_SNDTIMEO) with NULL timeout structure argument, which is an illegal usage of that function. The old code also didn't validate the return value of setsockopt, missing the bug completely. --- ports/unix/modusocket.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index fd4092a622845..a0f0fc25b1ce2 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -337,10 +337,9 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { struct timeval tv = {0,}; bool new_blocking = true; - if (timeout_in == mp_const_none) { - setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, NULL, 0); - setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, NULL, 0); - } else { + // Timeout of None means no timeout, which in POSIX is signified with 0 timeout, + // and that's how 'tv' is initialized above + if (timeout_in != mp_const_none) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t val = mp_obj_get_float(timeout_in); double ipart; @@ -354,14 +353,17 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { // for Python API it means non-blocking. if (tv.tv_sec == 0 && tv.tv_usec == 0) { new_blocking = false; - } else { - setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, - &tv, sizeof(struct timeval)); - setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, - &tv, sizeof(struct timeval)); } } + if (new_blocking) { + int r; + r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); + RAISE_ERRNO(r, errno); + r = setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); + RAISE_ERRNO(r, errno); + } + if (self->blocking != new_blocking) { socket_setblocking(self_in, mp_obj_new_bool(new_blocking)); } From 29865e3e58a89eace83fc1910221724363f55d64 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 8 May 2019 15:33:32 +1000 Subject: [PATCH 0062/1299] stm32/rtc: Allow overriding startup timeouts from mpconfigboard. --- ports/stm32/rtc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 4b9fbbda525da..a7c3f2068b8d8 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -342,18 +342,24 @@ STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse, bool rtc_need_init_finalise = true; } -#define PYB_LSE_TIMEOUT_VALUE 1000 // ST docs spec 2000 ms LSE startup, seems to be too pessimistic -#define PYB_LSI_TIMEOUT_VALUE 500 // this is way too pessimistic, typ. < 1ms -#define PYB_BYP_TIMEOUT_VALUE 150 +#ifndef MICROPY_HW_RTC_LSE_TIMEOUT_MS +#define MICROPY_HW_RTC_LSE_TIMEOUT_MS 1000 // ST docs spec 2000 ms LSE startup, seems to be too pessimistic +#endif +#ifndef MICROPY_HW_RTC_LSI_TIMEOUT_MS +#define MICROPY_HW_RTC_LSI_TIMEOUT_MS 500 // this is way too pessimistic, typ. < 1ms +#endif +#ifndef MICROPY_HW_RTC_BYP_TIMEOUT_MS +#define MICROPY_HW_RTC_BYP_TIMEOUT_MS 150 +#endif STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc) { // we already had a kick so now wait for the corresponding ready state... if (rtc_use_lse) { // we now have to wait for LSE ready or timeout - uint32_t timeout = PYB_LSE_TIMEOUT_VALUE; + uint32_t timeout = MICROPY_HW_RTC_LSE_TIMEOUT_MS; #if MICROPY_HW_RTC_USE_BYPASS if (RCC->BDCR & RCC_BDCR_LSEBYP) { - timeout = PYB_BYP_TIMEOUT_VALUE; + timeout = MICROPY_HW_RTC_BYP_TIMEOUT_MS; } #endif uint32_t tickstart = rtc_startup_tick; @@ -366,7 +372,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc) { // we now have to wait for LSI ready or timeout uint32_t tickstart = rtc_startup_tick; while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET) { - if ((HAL_GetTick() - tickstart ) > PYB_LSI_TIMEOUT_VALUE) { + if ((HAL_GetTick() - tickstart ) > MICROPY_HW_RTC_LSI_TIMEOUT_MS) { return HAL_TIMEOUT; } } From dac9d4767175541aaaaf0e2f873322f5f1db3b0c Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 21 Feb 2019 14:07:44 +1100 Subject: [PATCH 0063/1299] py/objgenerator: Fix handling of None passed as 2nd arg to throw(). Fixes issue #4527. --- py/objgenerator.c | 17 ++++++++++++++++- tests/basics/gen_yield_from_throw.py | 22 ++++++++++++++++++++-- tests/basics/generator_throw.py | 14 ++++++++++++-- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/py/objgenerator.c b/py/objgenerator.c index c306bb0c588ed..92bafea6a9f04 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -252,7 +252,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send); STATIC mp_obj_t gen_instance_close(mp_obj_t self_in); STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { - mp_obj_t exc = (n_args == 2) ? args[1] : args[2]; + // The signature of this function is: throw(type[, value[, traceback]]) + // CPython will pass all given arguments through the call chain and process them + // at the point they are used (native generators will handle them differently to + // user-defined generators with a throw() method). To save passing multiple + // values, MicroPython instead does partial processing here to reduce it down to + // one argument and passes that through: + // - if only args[1] is given, or args[2] is given but is None, args[1] is + // passed through (in the standard case it is an exception class or instance) + // - if args[2] is given and not None it is passed through (in the standard + // case it would be an exception instance and args[1] its corresponding class) + // - args[3] is always ignored + + mp_obj_t exc = args[1]; + if (n_args > 2 && args[2] != mp_const_none) { + exc = args[2]; + } mp_obj_t ret = gen_resume_and_raise(args[0], mp_const_none, exc); if (ret == MP_OBJ_STOP_ITERATION) { diff --git a/tests/basics/gen_yield_from_throw.py b/tests/basics/gen_yield_from_throw.py index 703158f4d42ab..804c53dda054b 100644 --- a/tests/basics/gen_yield_from_throw.py +++ b/tests/basics/gen_yield_from_throw.py @@ -1,8 +1,8 @@ def gen(): try: yield 1 - except ValueError: - print("got ValueError from upstream!") + except ValueError as e: + print("got ValueError from upstream!", repr(e.args)) yield "str1" raise TypeError @@ -16,3 +16,21 @@ def gen2(): print(next(g)) except TypeError: print("got TypeError from downstream!") + +# passing None as second argument to throw +g = gen2() +print(next(g)) +print(g.throw(ValueError, None)) +try: + print(next(g)) +except TypeError: + print("got TypeError from downstream!") + +# passing an exception instance as second argument to throw +g = gen2() +print(next(g)) +print(g.throw(ValueError, ValueError(123))) +try: + print(next(g)) +except TypeError: + print("got TypeError from downstream!") diff --git a/tests/basics/generator_throw.py b/tests/basics/generator_throw.py index bf5ff33a257bf..1b43c125eabc1 100644 --- a/tests/basics/generator_throw.py +++ b/tests/basics/generator_throw.py @@ -28,8 +28,8 @@ def gen(): def gen(): try: yield 123 - except GeneratorExit: - print('GeneratorExit') + except GeneratorExit as e: + print('GeneratorExit', repr(e.args)) yield 456 # thrown a class @@ -41,3 +41,13 @@ def gen(): g = gen() print(next(g)) print(g.throw(GeneratorExit())) + +# thrown an instance with None as second arg +g = gen() +print(next(g)) +print(g.throw(GeneratorExit(), None)) + +# thrown a class and instance +g = gen() +print(next(g)) +print(g.throw(GeneratorExit, GeneratorExit(123))) From 4268d0e1ace8ec42f08c7be328a5e5de21653b48 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 May 2019 13:49:07 +1000 Subject: [PATCH 0064/1299] py/objgenerator: Remove unneeded forward decl and clean up white space. --- py/objgenerator.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/py/objgenerator.c b/py/objgenerator.c index 92bafea6a9f04..29c7cb16d0cd8 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -247,10 +247,8 @@ STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) { return ret; } } - STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send); -STATIC mp_obj_t gen_instance_close(mp_obj_t self_in); STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { // The signature of this function is: throw(type[, value[, traceback]]) // CPython will pass all given arguments through the call chain and process them @@ -276,7 +274,6 @@ STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { return ret; } } - STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_instance_throw); STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { @@ -298,7 +295,6 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { return mp_const_none; } } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close); STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { From c0a1de3c216e86e679520fa50daf41dd9ac3ea78 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 May 2019 17:11:33 +1000 Subject: [PATCH 0065/1299] py/misc.h: Rename _MP_STRINGIFY to not use leading underscore in ident. Macro identifiers with a leading underscore are reserved. --- py/misc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/misc.h b/py/misc.h index e6d25b8509b4a..0aa4a5d2c6c91 100644 --- a/py/misc.h +++ b/py/misc.h @@ -47,8 +47,8 @@ typedef unsigned int uint; #endif // Classical double-indirection stringification of preprocessor macro's value -#define _MP_STRINGIFY(x) #x -#define MP_STRINGIFY(x) _MP_STRINGIFY(x) +#define MP_STRINGIFY_HELPER(x) #x +#define MP_STRINGIFY(x) MP_STRINGIFY_HELPER(x) // Static assertion macro #define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) From 99a8fa794089de2ca7292a49bdcb8a4550a06f4c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 23:30:57 +1000 Subject: [PATCH 0066/1299] esp8266/modmachine: Handle overflow of timer to get longer periods. Can now handle up to about 298 days maximum for millisecond periods. Fixes issue #4664. --- ports/esp8266/modmachine.c | 67 +++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index 58368b8f0b43f..ccde1e5ed89a3 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -167,12 +167,49 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep); +// These values are from the datasheet +#define ESP_TIMER_US_MIN (100) +#define ESP_TIMER_US_MAX (0xfffffff) +#define ESP_TIMER_MS_MAX (0x689d0) + typedef struct _esp_timer_obj_t { mp_obj_base_t base; os_timer_t timer; + uint32_t remain_ms; // if non-zero, remaining time to handle large periods + uint32_t period_ms; // if non-zero, periodic timer with a large period mp_obj_t callback; } esp_timer_obj_t; +STATIC void esp_timer_arm_ms(esp_timer_obj_t *self, uint32_t ms, bool repeat) { + if (ms <= ESP_TIMER_MS_MAX) { + self->remain_ms = 0; + self->period_ms = 0; + } else { + self->remain_ms = ms - ESP_TIMER_MS_MAX; + if (repeat) { + repeat = false; + self->period_ms = ms; + } else { + self->period_ms = 0; + } + ms = ESP_TIMER_MS_MAX; + } + os_timer_arm(&self->timer, ms, repeat); +} + +STATIC void esp_timer_arm_us(esp_timer_obj_t *self, uint32_t us, bool repeat) { + if (us < ESP_TIMER_US_MIN) { + us = ESP_TIMER_US_MIN; + } + if (us <= ESP_TIMER_US_MAX) { + self->remain_ms = 0; + self->period_ms = 0; + os_timer_arm_us(&self->timer, us, repeat); + } else { + esp_timer_arm_ms(self, us / 1000, repeat); + } +} + const mp_obj_type_t esp_timer_type; STATIC void esp_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -189,7 +226,21 @@ STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz STATIC void esp_timer_cb(void *arg) { esp_timer_obj_t *self = arg; - mp_sched_schedule(self->callback, self); + if (self->remain_ms != 0) { + // Handle periods larger than the maximum system period + uint32_t next_period_ms = self->remain_ms; + if (next_period_ms > ESP_TIMER_MS_MAX) { + next_period_ms = ESP_TIMER_MS_MAX; + } + self->remain_ms -= next_period_ms; + os_timer_arm(&self->timer, next_period_ms, false); + } else { + mp_sched_schedule(self->callback, self); + if (self->period_ms != 0) { + // A periodic timer with a larger period: reschedule it + esp_timer_arm_ms(self, self->period_ms, true); + } + } } STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -225,30 +276,30 @@ STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, size_t n_args, cons if (args[ARG_freq].u_obj != mp_const_none) { mp_float_t freq = mp_obj_get_float(args[ARG_freq].u_obj); if (freq < 0.001) { - os_timer_arm(&self->timer, (mp_int_t)(1000 / freq), args[ARG_mode].u_int); + esp_timer_arm_ms(self, (mp_int_t)(1000 / freq), args[ARG_mode].u_int); } else { - os_timer_arm_us(&self->timer, (mp_int_t)(1000000 / freq), args[ARG_mode].u_int); + esp_timer_arm_us(self, (mp_int_t)(1000000 / freq), args[ARG_mode].u_int); } } #else if (args[ARG_freq].u_int != 0xffffffff) { - os_timer_arm_us(&self->timer, 1000000 / args[ARG_freq].u_int, args[ARG_mode].u_int); + esp_timer_arm_us(self, 1000000 / args[ARG_freq].u_int, args[ARG_mode].u_int); } #endif else { mp_int_t period = args[ARG_period].u_int; mp_int_t hz = args[ARG_tick_hz].u_int; if (hz == 1000) { - os_timer_arm(&self->timer, period, args[ARG_mode].u_int); + esp_timer_arm_ms(self, period, args[ARG_mode].u_int); } else if (hz == 1000000) { - os_timer_arm_us(&self->timer, period, args[ARG_mode].u_int); + esp_timer_arm_us(self, period, args[ARG_mode].u_int); } else { // Use a long long to ensure that we don't either overflow or loose accuracy uint64_t period_us = (((uint64_t)period) * 1000000) / hz; if (period_us < 0x80000000ull) { - os_timer_arm_us(&self->timer, (mp_int_t)period_us, args[ARG_mode].u_int); + esp_timer_arm_us(self, (mp_int_t)period_us, args[ARG_mode].u_int); } else { - os_timer_arm(&self->timer, (mp_int_t)(period_us / 1000), args[ARG_mode].u_int); + esp_timer_arm_ms(self, (mp_int_t)(period_us / 1000), args[ARG_mode].u_int); } } } From f812394c33b0484f4bd24ef101c3c9250a74ab24 Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Thu, 9 May 2019 13:57:45 -0600 Subject: [PATCH 0067/1299] docs/esp32: Correct quickref for ESP32 hardware SPI with non-default IO. --- docs/esp32/quickref.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 5ac8aa3b2ff92..76fe0d9f9ed41 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -128,6 +128,8 @@ with timer ID of -1:: The period is in milliseconds. +.. _Pins_and_GPIO: + Pins and GPIO ------------- @@ -274,8 +276,13 @@ class:: Hardware SPI bus ---------------- -There are two hardware SPI channels that allow faster (up to 80Mhz) -transmission rates, but are only supported on a subset of pins. +There are two hardware SPI channels that allow faster transmission +rates (up to 80Mhz). These may be used on any IO pins that support the +required direction and are otherwise unused (see :ref:`Pins_and_GPIO`) +but if they are not configured to their default pins then they need to +pass through an extra layer of GPIO multiplexing, which can impact +their reliability at high speeds. Hardware SPI channels are limited +to 40MHz when used on pins other than the default ones listed below. ===== =========== ============ \ HSPI (id=1) VSPI (id=2) From ab93321e3160f2b688e8a60ad224debbdbd68c66 Mon Sep 17 00:00:00 2001 From: Henrik Vendelbo Date: Sun, 12 May 2019 11:22:48 +0200 Subject: [PATCH 0068/1299] py/persistentcode: Change "len" type to size_t for mp_obj_str_get_data. --- py/persistentcode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index c8d3bb8a6620c..cc6e161f427e4 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -560,7 +560,7 @@ STATIC void save_obj(mp_print_t *print, mp_obj_t o) { } else { obj_type = 'b'; } - mp_uint_t len; + size_t len; const char *str = mp_obj_str_get_data(o, &len); mp_print_bytes(print, &obj_type, 1); mp_print_uint(print, len); From 8586afa6f592cd8b886d5df04f587d1a92ad1bfc Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 13 May 2019 12:39:03 +1000 Subject: [PATCH 0069/1299] esp32/modnetwork: Change type to size_t for uses of mp_obj_str_get_data. --- ports/esp32/modnetwork.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 5d3c19b802702..b93715b6e6433 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -312,7 +312,7 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k // configure any parameters that are given if (n_args > 1) { - mp_uint_t len; + size_t len; const char *p; if (args[ARG_ssid].u_obj != mp_const_none) { p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len); @@ -553,7 +553,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs } case QS(MP_QSTR_essid): { req_if = WIFI_IF_AP; - mp_uint_t len; + size_t len; const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len); len = MIN(len, sizeof(cfg.ap.ssid)); memcpy(cfg.ap.ssid, s, len); @@ -572,7 +572,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs } case QS(MP_QSTR_password): { req_if = WIFI_IF_AP; - mp_uint_t len; + size_t len; const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len); len = MIN(len, sizeof(cfg.ap.password) - 1); memcpy(cfg.ap.password, s, len); From 7e21cf723a42321e759fdf77b24c04ce0a6afb29 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 13 May 2019 12:39:56 +1000 Subject: [PATCH 0070/1299] nrf: Change types to size_t for all uses of mp_obj_str_get_data. --- ports/nrf/boards/microbit/modules/microbitdisplay.c | 6 +++--- ports/nrf/boards/microbit/modules/microbitimage.c | 6 +++--- ports/nrf/modules/music/modmusic.c | 2 +- ports/nrf/modules/uos/microbitfs.c | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index 11ec004d073f7..936a3ec977568 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -90,7 +90,7 @@ mp_obj_t microbit_display_show_func(mp_uint_t n_args, const mp_obj_t *pos_args, if (mp_obj_is_str(image)) { // arg is a string object - mp_uint_t len; + size_t len; const char *str = mp_obj_str_get_data(image, &len); if (len == 0) { // There are no chars; do nothing. @@ -297,7 +297,7 @@ static void draw_object(mp_obj_t obj) { } else if (mp_obj_get_type(obj) == µbit_image_type) { microbit_display_show(display, (microbit_image_obj_t *)obj); } else if (mp_obj_is_str(obj)) { - mp_uint_t len; + size_t len; const char *str = mp_obj_str_get_data(obj, &len); if (len == 1) { microbit_display_show(display, microbit_image_for_char(str[0])); @@ -415,7 +415,7 @@ mp_obj_t microbit_display_scroll_func(mp_uint_t n_args, const mp_obj_t *pos_args microbit_display_obj_t *self = (microbit_display_obj_t*)pos_args[0]; mp_arg_val_t args[MP_ARRAY_SIZE(scroll_allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(scroll_allowed_args), scroll_allowed_args, args); - mp_uint_t len; + size_t len; const char* str = mp_obj_str_get_data(args[0].u_obj, &len); mp_obj_t iterable = scrolling_string_image_iterable(str, len, args[0].u_obj, args[3].u_bool /*monospace?*/, args[4].u_bool /*loop*/); microbit_display_animate(self, iterable, args[1].u_int /*delay*/, false/*clear*/, args[2].u_bool/*wait?*/); diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index aa519b4a2a361..9cba30f8782ec 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -216,7 +216,7 @@ STATIC mp_obj_t microbit_image_make_new(const mp_obj_type_t *type_in, mp_uint_t case 1: { if (mp_obj_is_str(args[0])) { // arg is a string object - mp_uint_t len; + size_t len; const char *str = mp_obj_str_get_data(args[0], &len); // make image from string if (len == 1) { @@ -880,7 +880,7 @@ static mp_obj_t string_image_facade_subscr(mp_obj_t self_in, mp_obj_t index_in, if (value == MP_OBJ_SENTINEL) { // Fill in image string_image_facade_t *self = (string_image_facade_t *)self_in; - mp_uint_t len; + size_t len; const char *text = mp_obj_str_get_data(self->string, &len); mp_uint_t index = mp_get_index(self->base.type, len, index_in, false); microbit_image_set_from_char(self->image, text[index]); @@ -935,7 +935,7 @@ mp_obj_t microbit_string_facade(mp_obj_t string) { static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) { facade_iterator_t *iter = (facade_iterator_t *)iter_in; - mp_uint_t len; + size_t len; const char *text = mp_obj_str_get_data(iter->string, &len); if (iter->index >= len) { return MP_OBJ_STOP_ITERATION; diff --git a/ports/nrf/modules/music/modmusic.c b/ports/nrf/modules/music/modmusic.c index 84a014c12df85..3730b3a72c7ee 100644 --- a/ports/nrf/modules/music/modmusic.c +++ b/ports/nrf/modules/music/modmusic.c @@ -126,7 +126,7 @@ void microbit_music_tick(void) { music_data->async_state = ASYNC_MUSIC_STATE_NEXT_NOTE; } else { // a note - mp_uint_t note_len; + size_t note_len; const char *note_str = mp_obj_str_get_data(note, ¬e_len); uint32_t delay_on = start_note(note_str, note_len, music_data->async_pin); music_data->async_wait_ticks = ticks + delay_on; diff --git a/ports/nrf/modules/uos/microbitfs.c b/ports/nrf/modules/uos/microbitfs.c index d4c5a119a123d..2ddf653cd7be4 100644 --- a/ports/nrf/modules/uos/microbitfs.c +++ b/ports/nrf/modules/uos/microbitfs.c @@ -377,7 +377,7 @@ STATIC file_descriptor_obj *microbit_file_descriptor_new(uint8_t start_chunk, bo } STATIC mp_obj_t microbit_remove(mp_obj_t filename) { - mp_uint_t name_len; + size_t name_len; const char *name = mp_obj_str_get_data(filename, &name_len); mp_uint_t index = microbit_find_file(name, name_len); if (index == 255) { @@ -487,7 +487,7 @@ STATIC mp_obj_t microbit_file_list(void) { } STATIC mp_obj_t microbit_file_size(mp_obj_t filename) { - mp_uint_t name_len; + size_t name_len; const char *name = mp_obj_str_get_data(filename, &name_len); uint8_t chunk = microbit_find_file(name, name_len); if (chunk == 255) { @@ -659,7 +659,7 @@ mp_obj_t uos_mbfs_open(size_t n_args, const mp_obj_t *args) { int read = -1; int text = -1; if (n_args == 2) { - mp_uint_t len; + size_t len; const char *mode = mp_obj_str_get_data(args[1], &len); for (mp_uint_t i = 0; i < len; i++) { if (mode[i] == 'r' || mode[i] == 'w') { @@ -677,7 +677,7 @@ mp_obj_t uos_mbfs_open(size_t n_args, const mp_obj_t *args) { } } } - mp_uint_t name_len; + size_t name_len; const char *filename = mp_obj_str_get_data(args[0], &name_len); file_descriptor_obj *res = microbit_file_open(filename, name_len, read == 0, text == 0); if (res == NULL) { From 7359a9e2f205008e05e99032a0b94fdc20281e0f Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Mon, 13 May 2019 00:42:17 +0200 Subject: [PATCH 0071/1299] stm32/dma: Initialise all members of DMA structs for H7 MCUs. --- ports/stm32/dma.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index a4ddcc42f91d6..0ccc66a2cfa41 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -85,7 +85,7 @@ struct _dma_descr_t { static const DMA_InitTypeDef dma_init_struct_spi_i2c = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32L4) + #elif defined(STM32H7) || defined(STM32L4) .Request = 0, #endif .Direction = 0, @@ -95,7 +95,7 @@ static const DMA_InitTypeDef dma_init_struct_spi_i2c = { .MemDataAlignment = DMA_MDATAALIGN_BYTE, .Mode = DMA_NORMAL, .Priority = DMA_PRIORITY_LOW, - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) .FIFOMode = DMA_FIFOMODE_DISABLE, .FIFOThreshold = DMA_FIFO_THRESHOLD_FULL, .MemBurst = DMA_MBURST_INC4, @@ -136,7 +136,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { static const DMA_InitTypeDef dma_init_struct_dac = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32L4) + #elif defined(STM32H7) || defined(STM32L4) .Request = 0, #endif .Direction = 0, @@ -146,7 +146,7 @@ static const DMA_InitTypeDef dma_init_struct_dac = { .MemDataAlignment = DMA_MDATAALIGN_BYTE, .Mode = DMA_NORMAL, .Priority = DMA_PRIORITY_HIGH, - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) .FIFOMode = DMA_FIFOMODE_DISABLE, .FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL, .MemBurst = DMA_MBURST_SINGLE, From 7c5cf59f8b9a5e62534e78558eb654bc664a3a6f Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 14 May 2019 14:45:54 +1000 Subject: [PATCH 0072/1299] extmod/modujson: Handle parsing of floats with + in the exponent. Fixes issue #4780. --- extmod/modujson.c | 2 +- tests/extmod/ujson_loads_float.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extmod/modujson.c b/extmod/modujson.c index 830b588fdc98f..f5c6428ef9c16 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -185,7 +185,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { cur = S_CUR(s); if (cur == '.' || cur == 'E' || cur == 'e') { flt = true; - } else if (cur == '-' || unichar_isdigit(cur)) { + } else if (cur == '+' || cur == '-' || unichar_isdigit(cur)) { // pass } else { break; diff --git a/tests/extmod/ujson_loads_float.py b/tests/extmod/ujson_loads_float.py index f1b8cc364c4ac..086853a2d4540 100644 --- a/tests/extmod/ujson_loads_float.py +++ b/tests/extmod/ujson_loads_float.py @@ -14,4 +14,5 @@ def my_print(o): my_print(json.loads('1e2')) my_print(json.loads('-2.3')) my_print(json.loads('-2e3')) +my_print(json.loads('-2e+3')) my_print(json.loads('-2e-3')) From 38cb95710a97fe65e901043ff435d4e3a90530e4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 14 May 2019 14:49:18 +1000 Subject: [PATCH 0073/1299] tests/pyb: Update UART expected output now that default timeout is 0. Follow up to commit 34942d0a72980173eca51b201f271f67bcae46b5 --- tests/pyb/uart.py.exp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/pyb/uart.py.exp b/tests/pyb/uart.py.exp index f3e6bbe2825f7..d302468ed2c26 100644 --- a/tests/pyb/uart.py.exp +++ b/tests/pyb/uart.py.exp @@ -12,8 +12,8 @@ UART XB UART YA UART YB ValueError Z -UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=1000, timeout_char=3, rxbuf=64) -UART(1, baudrate=2400, bits=8, parity=None, stop=1, flow=0, timeout=1000, timeout_char=7, rxbuf=64) +UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=64) +UART(1, baudrate=2400, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=7, rxbuf=64) 0 3 4 @@ -22,7 +22,7 @@ None 4 None None -UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=1000, timeout_char=3, rxbuf=8) -UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=1000, timeout_char=3, rxbuf=0) -UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=1000, timeout_char=3, rxbuf=4) -UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=1000, timeout_char=3, rxbuf=0) +UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=8) +UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=0) +UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=4) +UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=0) From 90fae9172a67f44e1fac967f628f26ddf90da963 Mon Sep 17 00:00:00 2001 From: stijn Date: Wed, 8 May 2019 16:16:17 +0200 Subject: [PATCH 0074/1299] py/objarray: Add support for memoryview.itemsize attribute. This allows figuring out the number of bytes in the memoryview object as len(memview) * memview.itemsize. The feature is enabled via MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE and is disabled by default. --- ports/unix/mpconfigport_coverage.h | 1 + py/mpconfig.h | 5 +++++ py/objarray.c | 16 ++++++++++++++++ tests/basics/memoryview_itemsize.py | 9 +++++++++ 4 files changed, 31 insertions(+) create mode 100644 tests/basics/memoryview_itemsize.py diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index f3fbee6bfa8af..b2f1d6e88ea59 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -40,6 +40,7 @@ #define MICROPY_MODULE_GETATTR (1) #define MICROPY_PY_DELATTR_SETATTR (1) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) +#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (1) #define MICROPY_PY_BUILTINS_NEXT2 (1) #define MICROPY_PY_BUILTINS_RANGE_BINOP (1) #define MICROPY_PY_BUILTINS_HELP (1) diff --git a/py/mpconfig.h b/py/mpconfig.h index 38b36a4b18762..2d857d8f6dbed 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -856,6 +856,11 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_MEMORYVIEW (0) #endif +// Whether to support memoryview.itemsize attribute +#ifndef MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE +#define MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE (0) +#endif + // Whether to support set object #ifndef MICROPY_PY_BUILTINS_SET #define MICROPY_PY_BUILTINS_SET (1) diff --git a/py/objarray.c b/py/objarray.c index 02f6dff528fc3..89d2f21806875 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -231,6 +231,19 @@ STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, return MP_OBJ_FROM_PTR(self); } + +#if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE +STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if (dest[0] != MP_OBJ_NULL) { + return; + } + if (attr == MP_QSTR_itemsize) { + mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); + dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL)); + } +} +#endif + #endif STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { @@ -560,6 +573,9 @@ const mp_obj_type_t mp_type_memoryview = { .getiter = array_iterator_new, .unary_op = array_unary_op, .binary_op = array_binary_op, + #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE + .attr = memoryview_attr, + #endif .subscr = array_subscr, .buffer_p = { .get_buffer = array_get_buffer }, }; diff --git a/tests/basics/memoryview_itemsize.py b/tests/basics/memoryview_itemsize.py new file mode 100644 index 0000000000000..108c69cfdc0f3 --- /dev/null +++ b/tests/basics/memoryview_itemsize.py @@ -0,0 +1,9 @@ +try: + memoryview(b'a').itemsize + from array import array +except: + print("SKIP") + raise SystemExit + +for code in ['b', 'h', 'i', 'l', 'q', 'f', 'd']: + print(memoryview(array(code)).itemsize) From a474ddf959fab641ab65631a8e140cf5bbda2541 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 14 May 2019 17:22:49 +1000 Subject: [PATCH 0075/1299] tests/basics: Add coverage tests for memoryview attributes. --- tests/basics/memoryview1.py | 6 ++++++ tests/basics/memoryview_itemsize.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/tests/basics/memoryview1.py b/tests/basics/memoryview1.py index c4cc6ffab726a..a0ac9e344932d 100644 --- a/tests/basics/memoryview1.py +++ b/tests/basics/memoryview1.py @@ -94,3 +94,9 @@ memoryview(array.array('i'))[0:2] = b'1234' except ValueError: print('ValueError') + +# invalid attribute +try: + memoryview(b'a').noexist +except AttributeError: + print('AttributeError') diff --git a/tests/basics/memoryview_itemsize.py b/tests/basics/memoryview_itemsize.py index 108c69cfdc0f3..60cb823087c45 100644 --- a/tests/basics/memoryview_itemsize.py +++ b/tests/basics/memoryview_itemsize.py @@ -7,3 +7,9 @@ for code in ['b', 'h', 'i', 'l', 'q', 'f', 'd']: print(memoryview(array(code)).itemsize) + +# shouldn't be able to store to the itemsize attribute +try: + memoryview(b'a').itemsize = 1 +except AttributeError: + print('AttributeError') From 993ca572ca122811e93167617625afd0b3a5d751 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 15 May 2019 15:46:16 +1000 Subject: [PATCH 0076/1299] tools/upip.py: Add support for multiple index URLs with custom default. The user can now select their own package index by either passing the "-i" command line option, or setting the upip.index_urls variable (before doing an install). The https://micropython.org/pi package index hosts packages from micropython-lib and will be searched first when installing a package. If a package is not found here then it will fallback to PyPI. --- tools/upip.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tools/upip.py b/tools/upip.py index 7ecf61e54b9bc..e3b8885169b46 100644 --- a/tools/upip.py +++ b/tools/upip.py @@ -16,6 +16,7 @@ debug = False +index_urls = ["https://micropython.org/pi", "https://pypi.org/pypi"] install_path = None cleanup_files = [] gzdict_sz = 16 + 15 @@ -156,11 +157,16 @@ def url_open(url): def get_pkg_metadata(name): - f = url_open("https://pypi.org/pypi/%s/json" % name) - try: - return json.load(f) - finally: - f.close() + for url in index_urls: + try: + f = url_open("%s/%s/json" % (url, name)) + except NotFoundError: + continue + try: + return json.load(f) + finally: + f.close() + raise NotFoundError("Package not found") def fatal(msg, exc=None): @@ -261,6 +267,7 @@ def help(): def main(): global debug + global index_urls global install_path install_path = None @@ -294,6 +301,9 @@ def main(): if l[0] == "#": continue to_install.append(l.rstrip()) + elif opt == "-i": + index_urls = [sys.argv[i]] + i += 1 elif opt == "--debug": debug = True else: From 123c065131e4933a237f17f180f1a01cbd07ee1e Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Mon, 13 May 2019 19:32:45 +0200 Subject: [PATCH 0077/1299] stm32/dma: Always reset and configure the H7 DMA peripheral. This is required for the H7 DMA to work. --- ports/stm32/dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 0ccc66a2cfa41..a1dd40c35224a 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -626,8 +626,8 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir dma_enable_clock(dma_id); - #if defined(STM32L4) - // Always reset and configure the L4 DMA peripheral + #if defined(STM32H7) || defined(STM32L4) + // Always reset and configure the H7 and L4 DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) // TODO: understand how L4 DMA works so this is not needed HAL_DMA_DeInit(dma); From 07af74daef4398540fa623244b4802c22cee3a12 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Mon, 13 May 2019 19:33:22 +0200 Subject: [PATCH 0078/1299] stm32/spi: Enable SPI IRQs and add IRQHandlers for H7 MCUs. The H7 HAL uses SPI IRQs when the SPI is running in DMA mode. --- ports/stm32/irq.h | 2 ++ ports/stm32/spi.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/ports/stm32/irq.h b/ports/stm32/irq.h index 9919013f894e5..bfed17ecffb0f 100644 --- a/ports/stm32/irq.h +++ b/ports/stm32/irq.h @@ -144,6 +144,8 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj); #define IRQ_PRI_CAN NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) +#define IRQ_PRI_SPI NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 8, 0) + // Interrupt priority for non-special timers. #define IRQ_PRI_TIMX NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 13, 0) diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index b7298b4aaaae2..545cb3365e6cc 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -97,6 +97,28 @@ const spi_t spi_obj[6] = { #endif }; +#if defined(STM32H7) +// STM32H7 HAL requires SPI IRQs to be enabled and handled. +#if defined(MICROPY_HW_SPI1_SCK) +void SPI1_IRQHandler(void) { IRQ_ENTER(SPI1_IRQn); HAL_SPI_IRQHandler(&SPIHandle1); IRQ_EXIT(SPI1_IRQn); } +#endif +#if defined(MICROPY_HW_SPI2_SCK) +void SPI2_IRQHandler(void) { IRQ_ENTER(SPI2_IRQn); HAL_SPI_IRQHandler(&SPIHandle2); IRQ_EXIT(SPI2_IRQn); } +#endif +#if defined(MICROPY_HW_SPI3_SCK) +void SPI3_IRQHandler(void) { IRQ_ENTER(SPI3_IRQn); HAL_SPI_IRQHandler(&SPIHandle3); IRQ_EXIT(SPI3_IRQn); } +#endif +#if defined(MICROPY_HW_SPI4_SCK) +void SPI4_IRQHandler(void) { IRQ_ENTER(SPI4_IRQn); HAL_SPI_IRQHandler(&SPIHandle4); IRQ_EXIT(SPI4_IRQn); } +#endif +#if defined(MICROPY_HW_SPI5_SCK) +void SPI5_IRQHandler(void) { IRQ_ENTER(SPI5_IRQn); HAL_SPI_IRQHandler(&SPIHandle5); IRQ_EXIT(SPI5_IRQn); } +#endif +#if defined(MICROPY_HW_SPI6_SCK) +void SPI6_IRQHandler(void) { IRQ_ENTER(SPI6_IRQn); HAL_SPI_IRQHandler(&SPIHandle6); IRQ_EXIT(SPI6_IRQn); } +#endif +#endif + void spi_init0(void) { // Initialise the SPI handles. // The structs live on the BSS so all other fields will be zero after a reset. @@ -231,11 +253,13 @@ void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate, // TODO allow to take a list of pins to use void spi_init(const spi_t *self, bool enable_nss_pin) { SPI_HandleTypeDef *spi = self->spi; + uint32_t irqn = 0; const pin_obj_t *pins[4] = { NULL, NULL, NULL, NULL }; if (0) { #if defined(MICROPY_HW_SPI1_SCK) } else if (spi->Instance == SPI1) { + irqn = SPI1_IRQn; #if defined(MICROPY_HW_SPI1_NSS) pins[0] = MICROPY_HW_SPI1_NSS; #endif @@ -249,6 +273,7 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { #endif #if defined(MICROPY_HW_SPI2_SCK) } else if (spi->Instance == SPI2) { + irqn = SPI2_IRQn; #if defined(MICROPY_HW_SPI2_NSS) pins[0] = MICROPY_HW_SPI2_NSS; #endif @@ -262,6 +287,7 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { #endif #if defined(MICROPY_HW_SPI3_SCK) } else if (spi->Instance == SPI3) { + irqn = SPI3_IRQn; #if defined(MICROPY_HW_SPI3_NSS) pins[0] = MICROPY_HW_SPI3_NSS; #endif @@ -275,6 +301,7 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { #endif #if defined(MICROPY_HW_SPI4_SCK) } else if (spi->Instance == SPI4) { + irqn = SPI4_IRQn; #if defined(MICROPY_HW_SPI4_NSS) pins[0] = MICROPY_HW_SPI4_NSS; #endif @@ -288,6 +315,7 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { #endif #if defined(MICROPY_HW_SPI5_SCK) } else if (spi->Instance == SPI5) { + irqn = SPI5_IRQn; #if defined(MICROPY_HW_SPI5_NSS) pins[0] = MICROPY_HW_SPI5_NSS; #endif @@ -301,6 +329,7 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { #endif #if defined(MICROPY_HW_SPI6_SCK) } else if (spi->Instance == SPI6) { + irqn = SPI6_IRQn; #if defined(MICROPY_HW_SPI6_NSS) pins[0] = MICROPY_HW_SPI6_NSS; #endif @@ -341,6 +370,13 @@ void spi_init(const spi_t *self, bool enable_nss_pin) { // an initialisation the next time we use it. dma_invalidate_channel(self->tx_dma_descr); dma_invalidate_channel(self->rx_dma_descr); + + #if defined(STM32H7) + NVIC_SetPriority(irqn, IRQ_PRI_SPI); + HAL_NVIC_EnableIRQ(irqn); + #else + (void)irqn; + #endif } void spi_deinit(const spi_t *spi_obj) { @@ -352,36 +388,42 @@ void spi_deinit(const spi_t *spi_obj) { __HAL_RCC_SPI1_FORCE_RESET(); __HAL_RCC_SPI1_RELEASE_RESET(); __HAL_RCC_SPI1_CLK_DISABLE(); + HAL_NVIC_DisableIRQ(SPI1_IRQn); #endif #if defined(MICROPY_HW_SPI2_SCK) } else if (spi->Instance == SPI2) { __HAL_RCC_SPI2_FORCE_RESET(); __HAL_RCC_SPI2_RELEASE_RESET(); __HAL_RCC_SPI2_CLK_DISABLE(); + HAL_NVIC_DisableIRQ(SPI2_IRQn); #endif #if defined(MICROPY_HW_SPI3_SCK) } else if (spi->Instance == SPI3) { __HAL_RCC_SPI3_FORCE_RESET(); __HAL_RCC_SPI3_RELEASE_RESET(); __HAL_RCC_SPI3_CLK_DISABLE(); + HAL_NVIC_DisableIRQ(SPI3_IRQn); #endif #if defined(MICROPY_HW_SPI4_SCK) } else if (spi->Instance == SPI4) { __HAL_RCC_SPI4_FORCE_RESET(); __HAL_RCC_SPI4_RELEASE_RESET(); __HAL_RCC_SPI4_CLK_DISABLE(); + HAL_NVIC_DisableIRQ(SPI4_IRQn); #endif #if defined(MICROPY_HW_SPI5_SCK) } else if (spi->Instance == SPI5) { __HAL_RCC_SPI5_FORCE_RESET(); __HAL_RCC_SPI5_RELEASE_RESET(); __HAL_RCC_SPI5_CLK_DISABLE(); + HAL_NVIC_DisableIRQ(SPI5_IRQn); #endif #if defined(MICROPY_HW_SPI6_SCK) } else if (spi->Instance == SPI6) { __HAL_RCC_SPI6_FORCE_RESET(); __HAL_RCC_SPI6_RELEASE_RESET(); __HAL_RCC_SPI6_CLK_DISABLE(); + HAL_NVIC_DisableIRQ(SPI6_IRQn); #endif } } From 1646eff8647d6665cb05cf56384299b49fbeb126 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Mon, 13 May 2019 19:44:14 +0200 Subject: [PATCH 0079/1299] stm32/irq: Fix IRQ_ENABLE_STATS stats config to work on all MCUs. Only the M4 and M7 MCUs have an FPU and FPU_IRQn, and FPU_IRQn is not always the last entry/IRQ number. --- ports/stm32/irq.c | 2 +- ports/stm32/irq.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ports/stm32/irq.c b/ports/stm32/irq.c index 7298a4b504c75..0100899733098 100644 --- a/ports/stm32/irq.c +++ b/ports/stm32/irq.c @@ -31,7 +31,7 @@ /// \moduleref pyb #if IRQ_ENABLE_STATS -uint32_t irq_stats[FPU_IRQn + 1] = {0}; +uint32_t irq_stats[IRQ_STATS_MAX] = {0}; #endif /// \function wfi() diff --git a/ports/stm32/irq.h b/ports/stm32/irq.h index bfed17ecffb0f..075791357c81f 100644 --- a/ports/stm32/irq.h +++ b/ports/stm32/irq.h @@ -39,7 +39,12 @@ #define IRQ_ENABLE_STATS (0) #if IRQ_ENABLE_STATS -extern uint32_t irq_stats[FPU_IRQn + 1]; +#if defined(STM32H7) +#define IRQ_STATS_MAX (256) +#else +#define IRQ_STATS_MAX (128) +#endif +extern uint32_t irq_stats[IRQ_STATS_MAX]; #define IRQ_ENTER(irq) ++irq_stats[irq] #define IRQ_EXIT(irq) #else From 746fcea7f88ee0cad6a9c0c98f6d5ba8de5b3fb7 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 14 May 2019 15:56:40 +0200 Subject: [PATCH 0080/1299] stm32/boards/NUCLEO_H743ZI: Enable SPI3 on this board. --- ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h | 8 ++++---- ports/stm32/boards/NUCLEO_H743ZI/pins.csv | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h index 68dece24ff293..8e227f1ba49d6 100644 --- a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h @@ -43,10 +43,10 @@ void NUCLEO_H743ZI_board_early_init(void); #define MICROPY_HW_I2C2_SDA (pin_F0) // SPI -//#define MICROPY_HW_SPI2_NSS (pin_I0) -//#define MICROPY_HW_SPI2_SCK (pin_I1) -//#define MICROPY_HW_SPI2_MISO (pin_B14) -//#define MICROPY_HW_SPI2_MOSI (pin_B15) +#define MICROPY_HW_SPI3_NSS (pin_A4) +#define MICROPY_HW_SPI3_SCK (pin_B3) +#define MICROPY_HW_SPI3_MISO (pin_B4) +#define MICROPY_HW_SPI3_MOSI (pin_B5) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) diff --git a/ports/stm32/boards/NUCLEO_H743ZI/pins.csv b/ports/stm32/boards/NUCLEO_H743ZI/pins.csv index 30910c4dd55c2..6a0532dbfe51e 100644 --- a/ports/stm32/boards/NUCLEO_H743ZI/pins.csv +++ b/ports/stm32/boards/NUCLEO_H743ZI/pins.csv @@ -20,6 +20,8 @@ D12,PB14 D13,PI1 D14,PB9 D15,PB8 +D22,PB5 +D23,PB3 DAC1,PA4 DAC2,PA5 LED1,PB0 From 2630d3e51f3f4ac933e556bb3df2953698ac74fc Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 15 May 2019 17:01:54 +1000 Subject: [PATCH 0081/1299] esp32/machine_uart: Implement UART.deinit() method. --- ports/esp32/machine_uart.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index b3c70de1e7b46..38cc1a8a9ac72 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -286,6 +286,13 @@ STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t } MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); +STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + uart_driver_delete(self->uart_num); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); + STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); size_t rxbufsize; @@ -327,7 +334,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbr STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, - + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, From 0557f0b74b67f91e4ced1c0ffd5d677f1699e64f Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 May 2019 00:30:04 +1000 Subject: [PATCH 0082/1299] esp32/network_ppp: Add a timeout for closing PPP connection. This also fixes deleting the PPP task, since eTaskGetState() never returns eDeleted. A limitation with this patch: once the PPP is deactivated (ppp.active(0)) it cannot be used again. A new PPP instance must be created instead. --- ports/esp32/network_ppp.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index da821478b8823..96d9ead305cc7 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -42,14 +42,17 @@ #include "lwip/dns.h" #include "netif/ppp/pppapi.h" +#define PPP_CLOSE_TIMEOUT_MS (4000) + typedef struct _ppp_if_obj_t { mp_obj_base_t base; bool active; bool connected; + volatile bool clean_close; ppp_pcb *pcb; mp_obj_t stream; SemaphoreHandle_t inactiveWaitSem; - TaskHandle_t client_task_handle; + volatile TaskHandle_t client_task_handle; struct netif pppif; } ppp_if_obj_t; @@ -64,7 +67,7 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { self->connected = (pppif->ip_addr.u_addr.ip4.addr != 0); break; case PPPERR_USER: - xSemaphoreGive(self->inactiveWaitSem); + self->clean_close = true; break; case PPPERR_CONNECT: self->connected = false; @@ -83,10 +86,9 @@ STATIC mp_obj_t ppp_make_new(mp_obj_t stream) { self->stream = stream; self->active = false; self->connected = false; - self->inactiveWaitSem = xSemaphoreCreateBinary(); + self->clean_close = false; self->client_task_handle = NULL; - assert(self->inactiveWaitSem != NULL); return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_1(ppp_make_new_obj, ppp_make_new); @@ -108,6 +110,8 @@ static void pppos_client_task(void *self_in) { pppos_input_tcpip(self->pcb, (u8_t*)buf, len); } } + + self->client_task_handle = NULL; vTaskDelete(NULL); } @@ -128,21 +132,24 @@ STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { pppapi_set_default(self->pcb); pppapi_connect(self->pcb, 0); - xTaskCreate(pppos_client_task, "ppp", 2048, self, 1, &self->client_task_handle); + xTaskCreate(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle); self->active = true; } else { if (!self->active) { return mp_const_false; } - // Wait for PPPERR_USER + // Wait for PPPERR_USER, with timeout pppapi_close(self->pcb, 0); - xSemaphoreTake(self->inactiveWaitSem, portMAX_DELAY); - xSemaphoreGive(self->inactiveWaitSem); + uint32_t t0 = mp_hal_ticks_ms(); + while (!self->clean_close && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { + mp_hal_delay_ms(10); + } // Shutdown task xTaskNotifyGive(self->client_task_handle); - while (eTaskGetState(self->client_task_handle) != eDeleted) { + t0 = mp_hal_ticks_ms(); + while (self->client_task_handle != NULL && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { mp_hal_delay_ms(10); } @@ -151,6 +158,7 @@ STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { self->pcb = NULL; self->active = false; self->connected = false; + self->clean_close = false; } } return mp_obj_new_bool(self->active); From e1e3704aa1406f9511728f54e62569ea08762d4b Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 15 May 2019 16:35:09 +1000 Subject: [PATCH 0083/1299] stm32/modmachine: Create dedicated asm function to branch to bootloader. Recent gcc versions (at least 9.1) give a warning about using "sp" in the clobber list. Such code is removed by this patch. A dedicated function is instead used to set SP and branch to the bootloader so the code has full control over what happens. Fixes issue #4785. --- ports/stm32/modmachine.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index f7b84bae6734d..7031dea91ca15 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -247,6 +247,15 @@ STATIC mp_obj_t machine_soft_reset(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); +__attribute__((naked)) void branch_to_bootloader(uint32_t r0, uint32_t addr) { + __asm volatile ( + "ldr r2, [r1, #0]\n" // get address of stack pointer + "msr msp, r2\n" // get stack pointer + "ldr r2, [r1, #4]\n" // get address of destination + "bx r2\n" // branch to bootloader + ); +} + // Activate the bootloader without BOOT* pins. STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { #if MICROPY_HW_ENABLE_USB @@ -271,8 +280,7 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) SCB_DisableICache(); SCB_DisableDCache(); #endif - __set_MSP(*(volatile uint32_t*)0x08000000); - ((void (*)(uint32_t)) *((volatile uint32_t*)(0x08000000 + 4)))(0x70ad0000); + branch_to_bootloader(0x70ad0000, 0x08000000); } if (n_args == 1 && mp_obj_is_str_or_bytes(args[0])) { @@ -285,28 +293,16 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) SCB_DisableICache(); SCB_DisableDCache(); #endif - __set_MSP(*(volatile uint32_t*)0x08000000); - ((void (*)(uint32_t)) *((volatile uint32_t*)(0x08000000 + 4)))(0x70ad0080); + branch_to_bootloader(0x70ad0080, 0x08000000); } #endif -#if defined(STM32F7) || defined(STM32H7) - // arm-none-eabi-gcc 4.9.0 does not correctly inline this - // MSP function, so we write it out explicitly here. - //__set_MSP(*((uint32_t*) 0x1FF00000)); - __ASM volatile ("movw r3, #0x0000\nmovt r3, #0x1FF0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp"); - - ((void (*)(void)) *((uint32_t*) 0x1FF00004))(); -#else + #if defined(STM32F7) || defined(STM32H7) + branch_to_bootloader(0, 0x1ff00000); + #else __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); - - // arm-none-eabi-gcc 4.9.0 does not correctly inline this - // MSP function, so we write it out explicitly here. - //__set_MSP(*((uint32_t*) 0x00000000)); - __ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp"); - - ((void (*)(void)) *((uint32_t*) 0x00000004))(); -#endif + branch_to_bootloader(0, 0x00000000); + #endif while (1); } From 016d9a40fe822a624449ad10486706991a97be29 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 14 May 2019 15:51:57 +0300 Subject: [PATCH 0084/1299] various: Add and update my copyright line based on git history. For modules I initially created or made substantial contributions to. --- extmod/moduselect.c | 1 + ports/esp8266/main.c | 1 + ports/esp8266/moduos.c | 1 + ports/unix/main.c | 1 + ports/unix/modffi.c | 2 +- ports/unix/modmachine.c | 1 + ports/unix/modos.c | 2 +- ports/unix/modtermios.c | 2 +- ports/unix/modtime.c | 1 + ports/unix/modusocket.c | 2 +- py/bc.h | 1 + py/binary.c | 1 + py/binary.h | 1 + py/frozenmod.h | 1 + py/gc.c | 1 + py/objdict.c | 1 + py/objexcept.c | 1 + py/objmodule.c | 1 + py/stream.h | 1 + py/vstr.c | 1 + 20 files changed, 20 insertions(+), 4 deletions(-) diff --git a/extmod/moduselect.c b/extmod/moduselect.c index a65fa6df29527..4963b4d5c6ea4 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George + * Copyright (c) 2015-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c index 3465e0446e4a3..8bfb2a0d8f892 100644 --- a/ports/esp8266/main.c +++ b/ports/esp8266/main.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George + * Copyright (c) 2015-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/esp8266/moduos.c b/ports/esp8266/moduos.c index 7a32c11c078f8..eab70e0638310 100644 --- a/ports/esp8266/moduos.c +++ b/ports/esp8266/moduos.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2015 Josef Gajdusek + * Copyright (c) 2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/main.c b/ports/unix/main.c index 8d455fa834e4f..cd2dc49a52788 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 0f8551e0a06d9..75d70e202bfe9 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2014-2018 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/modmachine.c b/ports/unix/modmachine.c index e2c44f94c26ab..392ce492584e1 100644 --- a/ports/unix/modmachine.c +++ b/ports/unix/modmachine.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/modos.c b/ports/unix/modos.c index d7ba1cfa1efc1..41ad3c147402a 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -3,8 +3,8 @@ * * The MIT License (MIT) * + * Copyright (c) 2014-2018 Paul Sokolovsky * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/modtermios.c b/ports/unix/modtermios.c index 7e46ba2f524fc..d8a742a00ef59 100644 --- a/ports/unix/modtermios.c +++ b/ports/unix/modtermios.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2014-2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c index a74b81f374e89..542c8196bef82 100644 --- a/ports/unix/modtime.c +++ b/ports/unix/modtime.c @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2014-2017 Paul Sokolovsky * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index a0f0fc25b1ce2..dd493b5ea6567 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -3,8 +3,8 @@ * * The MIT License (MIT) * + * Copyright (c) 2014-2018 Paul Sokolovsky * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/bc.h b/py/bc.h index 6d86fbdea92ee..0aadfa8a30578 100644 --- a/py/bc.h +++ b/py/bc.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/binary.c b/py/binary.c index bb2b718ced50b..eecded393d085 100644 --- a/py/binary.c +++ b/py/binary.c @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2014-2017 Paul Sokolovsky * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/py/binary.h b/py/binary.h index 0dae6a29e6617..4858c56279a2d 100644 --- a/py/binary.h +++ b/py/binary.h @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2014 Paul Sokolovsky * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/py/frozenmod.h b/py/frozenmod.h index 8cddef6819c59..9848a9afb8650 100644 --- a/py/frozenmod.h +++ b/py/frozenmod.h @@ -3,6 +3,7 @@ * * The MIT License (MIT) * + * Copyright (c) 2015 Paul Sokolovsky * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/py/gc.c b/py/gc.c index 2965059a1a25b..c763a839ec231 100644 --- a/py/gc.c +++ b/py/gc.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/objdict.c b/py/objdict.c index 015c2c72fef8f..0a223f7314c97 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/objexcept.c b/py/objexcept.c index d9258f9b5f6b3..1fb636f666156 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/objmodule.c b/py/objmodule.c index 9191c73ec3138..4a07913c5e2e2 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/stream.h b/py/stream.h index f4c6d30bdce1d..b6019bb38a543 100644 --- a/py/stream.h +++ b/py/stream.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/vstr.c b/py/vstr.c index 869b27805737a..6f480186e1d5f 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 653e1756c095a761dfea5bd91b94b9b2a150702c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 May 2019 18:02:44 +1000 Subject: [PATCH 0085/1299] various: Update early copyright years to match actual edit history. --- ports/unix/modos.c | 2 +- ports/unix/modtime.c | 2 +- ports/unix/modusocket.c | 2 +- py/binary.c | 2 +- py/binary.h | 2 +- py/frozenmod.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ports/unix/modos.c b/ports/unix/modos.c index 41ad3c147402a..161918d4dcec4 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014-2018 Paul Sokolovsky - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2018 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c index 542c8196bef82..0a463014dc0cb 100644 --- a/ports/unix/modtime.c +++ b/ports/unix/modtime.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014-2017 Paul Sokolovsky - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index dd493b5ea6567..8cbd3d077d2a9 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014-2018 Paul Sokolovsky - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/binary.c b/py/binary.c index eecded393d085..a142776c37cb2 100644 --- a/py/binary.c +++ b/py/binary.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014-2017 Paul Sokolovsky - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/binary.h b/py/binary.h index 4858c56279a2d..71182042f908b 100644 --- a/py/binary.h +++ b/py/binary.h @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/frozenmod.h b/py/frozenmod.h index 9848a9afb8650..8a477d028e036 100644 --- a/py/frozenmod.h +++ b/py/frozenmod.h @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2015 Paul Sokolovsky - * Copyright (c) 2014 Damien P. George + * Copyright (c) 2016 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 1f63e9b701aa6398ddb2e0db5e3a0f7f5adb4fcf Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 20 May 2019 14:37:28 +1000 Subject: [PATCH 0086/1299] stm32/adc: Fix VBAT_DIV to be 4 for STM32F411. Fixes issue #4794. --- ports/stm32/adc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 4f923245625b1..46fbbe73640a1 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -131,14 +131,15 @@ #if defined(STM32F091xC) #define VBAT_DIV (2) #elif defined(STM32F405xx) || defined(STM32F415xx) || \ - defined(STM32F407xx) || defined(STM32F417xx) || \ - defined(STM32F401xC) || defined(STM32F401xE) || \ - defined(STM32F411xE) + defined(STM32F407xx) || defined(STM32F417xx) || \ + defined(STM32F401xC) || defined(STM32F401xE) #define VBAT_DIV (2) -#elif defined(STM32F427xx) || defined(STM32F429xx) || \ +#elif defined(STM32F411xE) || defined(STM32F413xx) || \ + defined(STM32F427xx) || defined(STM32F429xx) || \ defined(STM32F437xx) || defined(STM32F439xx) || \ - defined(STM32F446xx) || defined(STM32F413xx) || \ - defined(STM32F722xx) || defined(STM32F723xx) || \ + defined(STM32F446xx) +#define VBAT_DIV (4) +#elif defined(STM32F722xx) || defined(STM32F723xx) || \ defined(STM32F732xx) || defined(STM32F733xx) || \ defined(STM32F746xx) || defined(STM32F765xx) || \ defined(STM32F767xx) || defined(STM32F769xx) From 8bec0e869d2285275487faebcc21a6278ebd311e Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 4 Aug 2018 16:18:52 +1000 Subject: [PATCH 0087/1299] docs/machine.I2C: Add writevto method to write a vector of byte bufs. This allows to efficiently send to an I2C slave data that is made up of more than one buffer. Instead of needing to allocate temporary memory to combine buffers together this new method allows to pass in a tuple or list of buffers. The name is based on the POSIX function writev() which has similar intentions and signature. The reasons for taking this approach (compared to having an interface with separate start/write/stop methods) are: - It's a backwards compatible extension. - It's convenient for the user. - It's efficient because there is only one Python call, then the C code can do everything in one go. - It's efficient on the I2C bus because the implementation can do everything in one go without pauses between blocks of bytes. - It should be possible to implement this extension in all ports, for hardware and software I2C. Further discussion is found in issue #3482, PR #4020 and PR #4763. --- docs/library/machine.I2C.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst index 71ca9b0d3b2c8..f589124378135 100644 --- a/docs/library/machine.I2C.rst +++ b/docs/library/machine.I2C.rst @@ -131,6 +131,20 @@ operations that target a given slave device. generated at the end of the transfer, even if a NACK is received. The function returns the number of ACKs that were received. +.. method:: I2C.writevto(addr, vector, stop=True) + + Write the bytes contained in *vector* to the slave specified by *addr*. + *vector* should be a tuple or list of objects with the buffer protocol. + The *addr* is sent once and then the bytes from each object in *vector* + are written out sequentially. The objects in *vector* may be zero bytes + in length in which case they don't contribute to the output. + + If a NACK is received following the write of a byte from one of the + objects in *vector* then the remaining bytes, and any remaining objects, + are not sent. If *stop* is true then a STOP condition is generated at + the end of the transfer, even if a NACK is received. The function + returns the number of ACKs that were received. + Memory operations ----------------- From 606ea2b10faccd94b2d9724055c0f6020b9c2fc6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 14:27:18 +1000 Subject: [PATCH 0088/1299] extmod/machine_i2c: Change C-level API to allow split I2C transactions. API is: int transfer( mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags ) --- extmod/machine_i2c.c | 154 +++++++++++++++++++++++++------------------ extmod/machine_i2c.h | 17 +++-- 2 files changed, 103 insertions(+), 68 deletions(-) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index c1a93ab041ae8..0202fc2bb8e24 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -180,9 +180,9 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) } // return value: -// >=0 - number of acks received +// >=0 - success; for read it's 0, for write it's number of acks received // <0 - error, with errno being the negative of the return value -int mp_machine_soft_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) { +int mp_machine_soft_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in; // start the I2C transaction @@ -192,7 +192,7 @@ int mp_machine_soft_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uin } // write the slave address - ret = mp_hal_i2c_write_byte(self, addr << 1); + ret = mp_hal_i2c_write_byte(self, (addr << 1) | (flags & MP_MACHINE_I2C_FLAG_READ)); if (ret < 0) { return ret; } else if (ret != 0) { @@ -201,69 +201,102 @@ int mp_machine_soft_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uin return -MP_ENODEV; } - // write the buffer to the I2C memory - int num_acks = 0; - while (len--) { - ret = mp_hal_i2c_write_byte(self, *src++); - if (ret < 0) { - return ret; - } else if (ret != 0) { - // nack received, stop sending - break; + int transfer_ret = 0; + for (; n--; ++bufs) { + size_t len = bufs->len; + uint8_t *buf = bufs->buf; + if (flags & MP_MACHINE_I2C_FLAG_READ) { + // read bytes from the slave into the given buffer(s) + while (len--) { + ret = mp_hal_i2c_read_byte(self, buf++, (n | len) == 0); + if (ret != 0) { + return ret; + } + } + } else { + // write bytes from the given buffer(s) to the slave + while (len--) { + ret = mp_hal_i2c_write_byte(self, *buf++); + if (ret < 0) { + return ret; + } else if (ret != 0) { + // nack received, stop sending + n = 0; + break; + } + ++transfer_ret; // count the number of acks + } } - ++num_acks; } // finish the I2C transaction - if (stop) { + if (flags & MP_MACHINE_I2C_FLAG_STOP) { ret = mp_hal_i2c_stop(self); if (ret != 0) { return ret; } } - return num_acks; + return transfer_ret; } -// return value: -// 0 - success -// <0 - error, with errno being the negative of the return value -int mp_machine_soft_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) { - machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in; - - // start the I2C transaction - int ret = mp_hal_i2c_start(self); - if (ret != 0) { - return ret; - } - - // write the slave address - ret = mp_hal_i2c_write_byte(self, (addr << 1) | 1); - if (ret < 0) { - return ret; - } else if (ret != 0) { - // nack received, release the bus cleanly - mp_hal_i2c_stop(self); - return -MP_ENODEV; - } - - // read the bytes from the slave - while (len--) { - ret = mp_hal_i2c_read_byte(self, dest++, len == 0); - if (ret != 0) { - return ret; +/******************************************************************************/ +// Generic helper functions + +// For use by ports that require a single buffer of data for a read/write transfer +int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { + size_t len; + uint8_t *buf; + if (n == 1) { + // Use given single buffer + len = bufs[0].len; + buf = bufs[0].buf; + } else { + // Combine buffers into a single one + len = 0; + for (size_t i = 0; i < n; ++i) { + len += bufs[i].len; + } + buf = m_new(uint8_t, len); + if (!(flags & MP_MACHINE_I2C_FLAG_READ)) { + len = 0; + for (size_t i = 0; i < n; ++i) { + memcpy(buf + len, bufs[i].buf, bufs[i].len); + len += bufs[i].len; + } } } - // finish the I2C transaction - if (stop) { - ret = mp_hal_i2c_stop(self); - if (ret != 0) { - return ret; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + int ret = i2c_p->transfer_single(self, addr, len, buf, flags); + + if (n > 1) { + if (flags & MP_MACHINE_I2C_FLAG_READ) { + // Copy data from single buffer to individual ones + len = 0; + for (size_t i = 0; i < n; ++i) { + memcpy(bufs[i].buf, buf + len, bufs[i].len); + len += bufs[i].len; + } } + m_del(uint8_t, buf, len); } - return 0; // success + return ret; +} + +STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self, uint16_t addr, uint8_t *dest, size_t len, bool stop) { + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_buf_t buf = {.len = len, .buf = dest}; + unsigned int flags = MP_MACHINE_I2C_FLAG_READ | (stop ? MP_MACHINE_I2C_FLAG_STOP : 0); + return i2c_p->transfer(self, addr, 1, &buf, flags); +} + +STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint8_t *src, size_t len, bool stop) { + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t*)src}; + unsigned int flags = stop ? MP_MACHINE_I2C_FLAG_STOP : 0; + return i2c_p->transfer(self, addr, 1, &buf, flags); } /******************************************************************************/ @@ -318,11 +351,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_obj_init); STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; mp_obj_t list = mp_obj_new_list(0, NULL); // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved for (int addr = 0x08; addr < 0x78; ++addr) { - int ret = i2c_p->writeto(self, addr, NULL, 0, true); + int ret = mp_machine_i2c_writeto(self, addr, NULL, 0, true); if (ret == 0) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); } @@ -407,12 +439,11 @@ MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write); STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; mp_int_t addr = mp_obj_get_int(args[1]); vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(args[2])); bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); - int ret = i2c_p->readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop); + int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop); if (ret < 0) { mp_raise_OSError(-ret); } @@ -422,12 +453,11 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_ STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; mp_int_t addr = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); - int ret = i2c_p->readfrom(self, addr, bufinfo.buf, bufinfo.len, stop); + int ret = mp_machine_i2c_readfrom(self, addr, bufinfo.buf, bufinfo.len, stop); if (ret < 0) { mp_raise_OSError(-ret); } @@ -437,12 +467,11 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; mp_int_t addr = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); - int ret = i2c_p->writeto(self, addr, bufinfo.buf, bufinfo.len, stop); + int ret = mp_machine_i2c_writeto(self, addr, bufinfo.buf, bufinfo.len, stop); if (ret < 0) { mp_raise_OSError(-ret); } @@ -453,19 +482,18 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machin STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; uint8_t memaddr_buf[4]; size_t memaddr_len = 0; for (int16_t i = addrsize - 8; i >= 0; i -= 8) { memaddr_buf[memaddr_len++] = memaddr >> i; } - int ret = i2c_p->writeto(self, addr, memaddr_buf, memaddr_len, false); + int ret = mp_machine_i2c_writeto(self, addr, memaddr_buf, memaddr_len, false); if (ret != memaddr_len) { // must generate STOP - i2c_p->writeto(self, addr, NULL, 0, true); + mp_machine_i2c_writeto(self, addr, NULL, 0, true); return ret; } - return i2c_p->readfrom(self, addr, buf, len, true); + return mp_machine_i2c_readfrom(self, addr, buf, len, true); } #define MAX_MEMADDR_SIZE (4) @@ -473,7 +501,6 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; // need some memory to create the buffer to send; try to use stack if possible uint8_t buf2_stack[MAX_MEMADDR_SIZE + BUF_STACK_SIZE]; @@ -493,7 +520,7 @@ STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t } memcpy(buf2 + memaddr_len, buf, len); - int ret = i2c_p->writeto(self, addr, buf2, memaddr_len + len, true); + int ret = mp_machine_i2c_writeto(self, addr, buf2, memaddr_len + len, true); if (buf2_alloc != 0) { m_del(uint8_t, buf2, buf2_alloc); } @@ -625,8 +652,7 @@ STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = { .stop = (int(*)(mp_obj_base_t*))mp_hal_i2c_stop, .read = mp_machine_soft_i2c_read, .write = mp_machine_soft_i2c_write, - .readfrom = mp_machine_soft_i2c_readfrom, - .writeto = mp_machine_soft_i2c_writeto, + .transfer = mp_machine_soft_i2c_transfer, }; const mp_obj_type_t machine_i2c_type = { diff --git a/extmod/machine_i2c.h b/extmod/machine_i2c.h index f5af6656f574d..f951c1f214973 100644 --- a/extmod/machine_i2c.h +++ b/extmod/machine_i2c.h @@ -28,15 +28,24 @@ #include "py/obj.h" +#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write +#define MP_MACHINE_I2C_FLAG_STOP (0x02) + +typedef struct _mp_machine_i2c_buf_t { + size_t len; + uint8_t *buf; +} mp_machine_i2c_buf_t; + // I2C protocol // the first 4 methods can be NULL, meaning operation is not supported +// transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor typedef struct _mp_machine_i2c_p_t { int (*start)(mp_obj_base_t *obj); int (*stop)(mp_obj_base_t *obj); int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack); int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len); - int (*readfrom)(mp_obj_base_t *obj, uint16_t addr, uint8_t *dest, size_t len, bool stop); - int (*writeto)(mp_obj_base_t *obj, uint16_t addr, const uint8_t *src, size_t len, bool stop); + int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); + int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags); } mp_machine_i2c_p_t; typedef struct _mp_machine_soft_i2c_obj_t { @@ -50,7 +59,7 @@ typedef struct _mp_machine_soft_i2c_obj_t { extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_dict_t mp_machine_soft_i2c_locals_dict; -int mp_machine_soft_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop); -int mp_machine_soft_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop); +int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); +int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); #endif // MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H From 38ac697b451a5111075cdcaf305e1bdf28d268b2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 14:39:27 +1000 Subject: [PATCH 0089/1299] stm32/machine_i2c: Update to support new C-level I2C API. --- ports/stm32/machine_i2c.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 940e98d715fa8..037401d862a77 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -109,14 +109,34 @@ void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, uint32_t i2c_init(self->i2c, self->scl, self->sda, freq); } -int machine_hard_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) { +int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - return i2c_readfrom(self->i2c, addr, dest, len, stop); -} -int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) { - machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - return i2c_writeto(self->i2c, addr, src, len, stop); + size_t remain_len = 0; + for (size_t i = 0; i < n; ++i) { + remain_len += bufs[i].len; + } + + int ret = i2c_start_addr(self->i2c, flags & MP_MACHINE_I2C_FLAG_READ, addr, remain_len, flags & MP_MACHINE_I2C_FLAG_STOP); + if (ret < 0) { + return ret; + } + + int num_acks = 0; // only valid for write; for read it'll be 0 + for (; n--; ++bufs) { + remain_len -= bufs->len; + if (flags & MP_MACHINE_I2C_FLAG_READ) { + ret = i2c_read(self->i2c, bufs->buf, bufs->len, remain_len); + } else { + ret = i2c_write(self->i2c, bufs->buf, bufs->len, remain_len); + } + if (ret < 0) { + return ret; + } + num_acks += ret; + } + + return num_acks; } #else @@ -174,8 +194,7 @@ STATIC void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, u mp_hal_pin_open_drain(self->sda); } -#define machine_hard_i2c_readfrom mp_machine_soft_i2c_readfrom -#define machine_hard_i2c_writeto mp_machine_soft_i2c_writeto +#define machine_hard_i2c_transfer mp_machine_soft_i2c_transfer #endif @@ -240,8 +259,7 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz } STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { - .readfrom = machine_hard_i2c_readfrom, - .writeto = machine_hard_i2c_writeto, + .transfer = machine_hard_i2c_transfer, }; STATIC const mp_obj_type_t machine_hard_i2c_type = { From bb29bde102e089341db27c431cd10362bb8f825f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 18:19:53 +1000 Subject: [PATCH 0090/1299] nrf/machine/i2c: Update to support new C-level I2C API. --- ports/nrf/modules/machine/i2c.c | 37 ++++++++++----------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/ports/nrf/modules/machine/i2c.c b/ports/nrf/modules/machine/i2c.c index 8b79342a30de0..1d8971612169d 100644 --- a/ports/nrf/modules/machine/i2c.c +++ b/ports/nrf/modules/machine/i2c.c @@ -99,35 +99,20 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(self); } -int machine_hard_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) { +int machine_hard_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)self_in; nrfx_twi_enable(&self->p_twi); - nrfx_err_t err_code = nrfx_twi_rx(&self->p_twi, addr, dest, len); - - if (err_code != NRFX_SUCCESS) { - if (err_code == NRFX_ERROR_DRV_TWI_ERR_ANACK) { - return -MP_ENODEV; - } - else if (err_code == NRFX_ERROR_DRV_TWI_ERR_DNACK) { - return -MP_EIO; - } - return -MP_ETIMEDOUT; + nrfx_err_t err_code; + int transfer_ret = 0; + if (flags & MP_MACHINE_I2C_FLAG_READ) { + err_code = nrfx_twi_rx(&self->p_twi, addr, buf, len); + } else { + err_code = nrfx_twi_tx(&self->p_twi, addr, buf, len, (flags & MP_MACHINE_I2C_FLAG_STOP) == 0); + transfer_ret = len; } - nrfx_twi_disable(&self->p_twi); - - return 0; -} - -int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) { - machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)self_in; - - nrfx_twi_enable(&self->p_twi); - - nrfx_err_t err_code = nrfx_twi_tx(&self->p_twi, addr, src, len, !stop); - if (err_code != NRFX_SUCCESS) { if (err_code == NRFX_ERROR_DRV_TWI_ERR_ANACK) { return -MP_ENODEV; @@ -140,12 +125,12 @@ int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_ nrfx_twi_disable(&self->p_twi); - return len; + return transfer_ret; } STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { - .readfrom = machine_hard_i2c_readfrom, - .writeto = machine_hard_i2c_writeto, + .transfer = mp_machine_i2c_transfer_adaptor, + .transfer_single = machine_hard_i2c_transfer_single, }; STATIC const mp_obj_type_t machine_hard_i2c_type = { From 647b27d02891798a0d9a89b465056b1d37786d66 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 18:20:19 +1000 Subject: [PATCH 0091/1299] zephyr/machine_i2c: Update to support new C-level I2C API. --- ports/zephyr/machine_i2c.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/ports/zephyr/machine_i2c.c b/ports/zephyr/machine_i2c.c index bc9851a00c8e7..0a9e9cfaba539 100644 --- a/ports/zephyr/machine_i2c.c +++ b/ports/zephyr/machine_i2c.c @@ -92,7 +92,7 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(self); } -STATIC int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, uint8_t *buf, size_t len, bool stop, bool read) { +STATIC int machine_hard_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) { machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t *)self_in; struct i2c_msg msg; int ret; @@ -101,7 +101,7 @@ STATIC int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, uint msg.len = len; msg.flags = 0; - if (read) { + if (flags & MP_MACHINE_I2C_FLAG_READ) { msg.flags |= I2C_MSG_READ; } else { msg.flags |= I2C_MSG_WRITE; @@ -111,7 +111,7 @@ STATIC int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, uint msg.flags |= I2C_MSG_RESTART; } - if (stop) { + if (flags & MP_MACHINE_I2C_FLAG_STOP) { msg.flags |= I2C_MSG_STOP; self->restart = false; } else { @@ -122,17 +122,9 @@ STATIC int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, uint return (ret < 0) ? -MP_EIO : len; } -STATIC int machine_hard_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) { - return machine_hard_i2c_transfer(self_in, addr, dest, len, stop, true); -} - -STATIC int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) { - return machine_hard_i2c_transfer(self_in, addr, (uint8_t*)src, len, stop, false); -} - STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = { - .readfrom = machine_hard_i2c_readfrom, - .writeto = machine_hard_i2c_writeto, + .transfer = mp_machine_i2c_transfer_adaptor, + .transfer_single = machine_hard_i2c_transfer_single, }; STATIC const mp_obj_type_t machine_hard_i2c_type = { From 8bcb552d9755c63d819dc81b901c5b5dc8e3cc8f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 18:25:18 +1000 Subject: [PATCH 0092/1299] extmod/machine_i2c: Remove need for temporary memory in writemem() call. --- extmod/machine_i2c.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 0202fc2bb8e24..63493141cbb0d 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -496,35 +496,25 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a return mp_machine_i2c_readfrom(self, addr, buf, len, true); } -#define MAX_MEMADDR_SIZE (4) -#define BUF_STACK_SIZE (12) - STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - // need some memory to create the buffer to send; try to use stack if possible - uint8_t buf2_stack[MAX_MEMADDR_SIZE + BUF_STACK_SIZE]; - uint8_t *buf2; - size_t buf2_alloc = 0; - if (len <= BUF_STACK_SIZE) { - buf2 = buf2_stack; - } else { - buf2_alloc = MAX_MEMADDR_SIZE + len; - buf2 = m_new(uint8_t, buf2_alloc); - } - - // create the buffer to send + // Create buffer with memory address size_t memaddr_len = 0; + uint8_t memaddr_buf[4]; for (int16_t i = addrsize - 8; i >= 0; i -= 8) { - buf2[memaddr_len++] = memaddr >> i; + memaddr_buf[memaddr_len++] = memaddr >> i; } - memcpy(buf2 + memaddr_len, buf, len); - int ret = mp_machine_i2c_writeto(self, addr, buf2, memaddr_len + len, true); - if (buf2_alloc != 0) { - m_del(uint8_t, buf2, buf2_alloc); - } - return ret; + // Create partial write buffers + mp_machine_i2c_buf_t bufs[2] = { + {.len = memaddr_len, .buf = memaddr_buf}, + {.len = len, .buf = (uint8_t*)buf}, + }; + + // Do I2C transfer + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP); } STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = { From b10d0664be04d0ff242fc11e7d246b97e3101f1b Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 18:33:54 +1000 Subject: [PATCH 0093/1299] extmod/machine_i2c: Add i2c.writevto() that can write a vector of bufs. For example: i2c.writevto(addr, (buf1, buf2)). This allows to efficiently (wrt memory) write data composed of separate buffers, such as a command followed by a large amount of data. --- extmod/machine_i2c.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 63493141cbb0d..0687aa9d2d456 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -480,6 +480,52 @@ STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto); +STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) { + mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); + mp_int_t addr = mp_obj_get_int(args[1]); + + // Get the list of data buffer(s) to write + size_t nitems; + const mp_obj_t *items; + mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items); + + // Get the stop argument + bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); + + // Extract all buffer data, skipping zero-length buffers + size_t alloc = nitems == 0 ? 1 : nitems; + size_t nbufs = 0; + mp_machine_i2c_buf_t *bufs = mp_local_alloc(alloc * sizeof(mp_machine_i2c_buf_t)); + for (; nitems--; ++items) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len > 0) { + bufs[nbufs].len = bufinfo.len; + bufs[nbufs++].buf = bufinfo.buf; + } + } + + // Make sure there is at least one buffer, empty if needed + if (nbufs == 0) { + bufs[0].len = 0; + bufs[0].buf = NULL; + nbufs = 1; + } + + // Do the I2C transfer + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0); + mp_local_free(bufs); + + if (ret < 0) { + mp_raise_OSError(-ret); + } + + // Return number of acks received + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto); + STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); uint8_t memaddr_buf[4]; @@ -601,6 +647,7 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) }, { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) }, { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) }, + { MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) }, // memory operations { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) }, From 02afc0d241dbd0efb985ba5a7ded9cea616ffcd7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 May 2019 18:46:37 +1000 Subject: [PATCH 0094/1299] drivers/display/ssd1306.py: Change to use new i2c.writevto() method. Fixes issue #3482. --- drivers/display/ssd1306.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py index 178b4911d7125..f93a451e85e6e 100644 --- a/drivers/display/ssd1306.py +++ b/drivers/display/ssd1306.py @@ -96,6 +96,7 @@ def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False): self.i2c = i2c self.addr = addr self.temp = bytearray(2) + self.write_list = [b'\x40', None] # Co=0, D/C#=1 super().__init__(width, height, external_vcc) def write_cmd(self, cmd): @@ -104,12 +105,8 @@ def write_cmd(self, cmd): self.i2c.writeto(self.addr, self.temp) def write_data(self, buf): - self.temp[0] = self.addr << 1 - self.temp[1] = 0x40 # Co=0, D/C#=1 - self.i2c.start() - self.i2c.write(self.temp) - self.i2c.write(buf) - self.i2c.stop() + self.write_list[1] = buf + self.i2c.writevto(self.addr, self.write_list) class SSD1306_SPI(SSD1306): From 1b3c1f9e6bf4669d2eb9c85c07bc83105aa97556 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 20 May 2019 15:16:14 +1000 Subject: [PATCH 0095/1299] lib/stm32lib: Update library to fix UART9/10 baudrate on F4 MCUs. --- lib/stm32lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/stm32lib b/lib/stm32lib index a5e93de184798..615329f1a61bd 160000 --- a/lib/stm32lib +++ b/lib/stm32lib @@ -1 +1 @@ -Subproject commit a5e93de18479879dd129cf6272cfd75e0c794bd4 +Subproject commit 615329f1a61bd0689bfb095cb3fd74865cca88ff From e5e472198c0cf5cbac8fdf0a9ad5037a9c995f02 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 20 May 2019 15:46:01 +1000 Subject: [PATCH 0096/1299] docs/pyboard/quickref: Refer to new machine.I2C instead of old pyb.I2C. On stm32 boards, machine.I2C is now preferred over pyb.I2C. --- docs/pyboard/quickref.rst | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/docs/pyboard/quickref.rst b/docs/pyboard/quickref.rst index 5d4985f5879db..b1195ce7c86fb 100644 --- a/docs/pyboard/quickref.rst +++ b/docs/pyboard/quickref.rst @@ -199,16 +199,25 @@ See :ref:`pyb.SPI `. :: I2C bus ------- -See :ref:`pyb.I2C `. :: +Hardware I2C is available on the X and Y halves of the pyboard via ``I2C('X')`` +and ``I2C('Y')``. Alternatively pass in the integer identifier of the peripheral, +eg ``I2C(1)``. Software I2C is also available by explicitly specifying the +``scl`` and ``sda`` pins instead of the bus name. For more details see +:ref:`machine.I2C `. :: - from pyb import I2C + from machine import I2C - i2c = I2C(1, I2C.MASTER, baudrate=100000) - i2c.scan() # returns list of slave addresses - i2c.send('hello', 0x42) # send 5 bytes to slave with address 0x42 - i2c.recv(5, 0x42) # receive 5 bytes from slave - i2c.mem_read(2, 0x42, 0x10) # read 2 bytes from slave 0x42, slave memory 0x10 - i2c.mem_write('xy', 0x42, 0x10) # write 2 bytes to slave 0x42, slave memory 0x10 + i2c = I2C('X', freq=400000) # create hardware I2c object + i2c = I2C(scl='X1', sda='X2', freq=100000) # create software I2C object + + i2c.scan() # returns list of slave addresses + i2c.writeto(0x42, 'hello') # write 5 bytes to slave with address 0x42 + i2c.readfrom(0x42, 5) # read 5 bytes from slave + + i2c.readfrom_mem(0x42, 0x10, 2) # read 2 bytes from slave 0x42, slave memory 0x10 + i2c.writeto_mem(0x42, 0x10, 'xy') # write 2 bytes to slave 0x42, slave memory 0x10 + +Note: for legacy I2C support see :ref:`pyb.I2C `. CAN bus (controller area network) --------------------------------- From ed2b6ea0a8f4d55a373af032faeca128c0741317 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 18 Apr 2019 10:31:44 +1000 Subject: [PATCH 0097/1299] stm32/i2c: Make timeout for hardware I2C configurable. Previously the hardware I2C timeout was hard coded to 50ms which isn't guaranteed to be enough depending on the clock stretching specs of the I2C device(s) in use. This patch ensures the hardware I2C implementation honors the existing timeout argument passed to the machine.I2C constructor. The default timeout for software and hardware I2C is now 50ms. --- ports/stm32/accel.c | 4 +++- ports/stm32/i2c.c | 28 ++++++++++++++++++++-------- ports/stm32/i2c.h | 2 +- ports/stm32/machine_i2c.c | 18 ++++++++++-------- ports/stm32/mpconfigboard_common.h | 3 +++ 5 files changed, 37 insertions(+), 18 deletions(-) diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index 0d7708c0934fc..73ddcf8cfabcf 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -46,6 +46,8 @@ /// /// Raw values are between -32 and 31. +#define I2C_TIMEOUT_MS (50) + #define MMA_ADDR (76) #define MMA_REG_X (0) #define MMA_REG_Y (1) @@ -62,7 +64,7 @@ void accel_init(void) { STATIC void accel_start(void) { // start the I2C bus in master mode - i2c_init(I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 400000); + i2c_init(I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 400000, I2C_TIMEOUT_MS); // turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again mp_hal_pin_low(MICROPY_HW_MMA_AVDD_PIN); // turn off diff --git a/ports/stm32/i2c.c b/ports/stm32/i2c.c index 109b9418f8665..06e26d9124595 100644 --- a/ports/stm32/i2c.c +++ b/ports/stm32/i2c.c @@ -30,11 +30,11 @@ #if MICROPY_HW_ENABLE_HW_I2C -#define I2C_POLL_TIMEOUT_MS (50) - #if defined(STM32F4) -int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq) { +STATIC uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C]; + +int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq, uint16_t timeout_ms) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); // Init pins @@ -45,6 +45,9 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr return -MP_EPERM; } + // Save timeout value + i2c_timeout_ms[i2c_id] = timeout_ms; + // Force reset I2C peripheral RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST << i2c_id; RCC->APB1RSTR &= ~(RCC_APB1RSTR_I2C1RST << i2c_id); @@ -88,9 +91,10 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr } STATIC int i2c_wait_sr1_set(i2c_t *i2c, uint32_t mask) { + uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (!(i2c->SR1 & mask)) { - if (HAL_GetTick() - t0 >= I2C_POLL_TIMEOUT_MS) { + if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } @@ -99,9 +103,10 @@ STATIC int i2c_wait_sr1_set(i2c_t *i2c, uint32_t mask) { } STATIC int i2c_wait_stop(i2c_t *i2c) { + uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (i2c->CR1 & I2C_CR1_STOP) { - if (HAL_GetTick() - t0 >= I2C_POLL_TIMEOUT_MS) { + if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } @@ -264,7 +269,9 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) { #elif defined(STM32F0) || defined(STM32F7) -int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq) { +STATIC uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C]; + +int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq, uint16_t timeout_ms) { uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); // Init pins @@ -275,6 +282,9 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr return -MP_EPERM; } + // Save timeout value + i2c_timeout_ms[i2c_id] = timeout_ms; + // Enable I2C peripheral clock RCC->APB1ENR |= RCC_APB1ENR_I2C1EN << i2c_id; volatile uint32_t tmp = RCC->APB1ENR; // delay after RCC clock enable @@ -303,9 +313,10 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr } STATIC int i2c_wait_cr2_clear(i2c_t *i2c, uint32_t mask) { + uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (i2c->CR2 & mask) { - if (HAL_GetTick() - t0 >= I2C_POLL_TIMEOUT_MS) { + if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } @@ -314,9 +325,10 @@ STATIC int i2c_wait_cr2_clear(i2c_t *i2c, uint32_t mask) { } STATIC int i2c_wait_isr_set(i2c_t *i2c, uint32_t mask) { + uint32_t i2c_id = ((uint32_t)i2c - I2C1_BASE) / (I2C2_BASE - I2C1_BASE); uint32_t t0 = HAL_GetTick(); while (!(i2c->ISR & mask)) { - if (HAL_GetTick() - t0 >= I2C_POLL_TIMEOUT_MS) { + if (HAL_GetTick() - t0 >= i2c_timeout_ms[i2c_id]) { i2c->CR1 &= ~I2C_CR1_PE; return -MP_ETIMEDOUT; } diff --git a/ports/stm32/i2c.h b/ports/stm32/i2c.h index 5599f41235cf4..4846f1cf3ab52 100644 --- a/ports/stm32/i2c.h +++ b/ports/stm32/i2c.h @@ -55,7 +55,7 @@ void i2c_er_irq_handler(mp_uint_t i2c_id); typedef I2C_TypeDef i2c_t; -int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq); +int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t freq, uint16_t timeout); int i2c_start_addr(i2c_t *i2c, int rd_wrn, uint16_t addr, size_t len, bool stop); int i2c_read(i2c_t *i2c, uint8_t *dest, size_t len, size_t next_len); int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len); diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 037401d862a77..5acf9c7d6eea2 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -37,6 +37,8 @@ STATIC const mp_obj_type_t machine_hard_i2c_type; +#define I2C_POLL_DEFAULT_TIMEOUT_US (50000) // 50ms + #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) typedef struct _machine_hard_i2c_obj_t { @@ -104,9 +106,9 @@ STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp #endif } -void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, uint32_t timeout) { - (void)timeout; - i2c_init(self->i2c, self->scl, self->sda, freq); +void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, uint32_t timeout_us) { + uint32_t timeout_ms = (timeout_us + 999) / 1000; + i2c_init(self->i2c, self->scl, self->sda, freq, timeout_ms); } int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { @@ -147,22 +149,22 @@ typedef mp_machine_soft_i2c_obj_t machine_hard_i2c_obj_t; STATIC machine_hard_i2c_obj_t machine_hard_i2c_obj[] = { #if defined(MICROPY_HW_I2C1_SCL) - {{&machine_hard_i2c_type}, 1, 500, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, + {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, #else {{NULL}, 0, 0, NULL, NULL}, #endif #if defined(MICROPY_HW_I2C2_SCL) - {{&machine_hard_i2c_type}, 1, 500, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, + {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, #else {{NULL}, 0, 0, NULL, NULL}, #endif #if defined(MICROPY_HW_I2C3_SCL) - {{&machine_hard_i2c_type}, 1, 500, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, + {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, #else {{NULL}, 0, 0, NULL, NULL}, #endif #if defined(MICROPY_HW_I2C4_SCL) - {{&machine_hard_i2c_type}, 1, 500, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, + {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, #else {{NULL}, 0, 0, NULL, NULL}, #endif @@ -209,7 +211,7 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_POLL_DEFAULT_TIMEOUT_US} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 4348f50bdd51e..f3a3d48e7f321 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -138,6 +138,7 @@ #define MP_HAL_UNIQUE_ID_ADDRESS (0x1ffff7ac) #define PYB_EXTI_NUM_VECTORS (23) +#define MICROPY_HW_MAX_I2C (2) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) @@ -146,6 +147,7 @@ #define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7a10) #define PYB_EXTI_NUM_VECTORS (23) +#define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_TIMER (14) #if defined(UART10) #define MICROPY_HW_MAX_UART (10) @@ -169,6 +171,7 @@ #endif #define PYB_EXTI_NUM_VECTORS (24) +#define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) From ddc657658af9ef74a7d891700a6e576c4fb5ff8e Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 21 May 2019 12:38:34 +1000 Subject: [PATCH 0098/1299] stm32/machine_i2c: Simplify ROM initialisation of static HW I2C objects. --- ports/stm32/machine_i2c.c | 36 +++++++++--------------------- ports/stm32/mpconfigboard_common.h | 2 ++ 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 5acf9c7d6eea2..2aebb9426e63b 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -48,26 +48,18 @@ typedef struct _machine_hard_i2c_obj_t { mp_hal_pin_obj_t sda; } machine_hard_i2c_obj_t; -STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[] = { +STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = { #if defined(MICROPY_HW_I2C1_SCL) - {{&machine_hard_i2c_type}, I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, - #else - {{NULL}, NULL, NULL, NULL}, + [0] = {{&machine_hard_i2c_type}, I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, #endif #if defined(MICROPY_HW_I2C2_SCL) - {{&machine_hard_i2c_type}, I2C2, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, - #else - {{NULL}, NULL, NULL, NULL}, + [1] = {{&machine_hard_i2c_type}, I2C2, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, #endif #if defined(MICROPY_HW_I2C3_SCL) - {{&machine_hard_i2c_type}, I2C3, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, - #else - {{NULL}, NULL, NULL, NULL}, + [2] = {{&machine_hard_i2c_type}, I2C3, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, #endif #if defined(MICROPY_HW_I2C4_SCL) - {{&machine_hard_i2c_type}, I2C4, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, - #else - {{NULL}, NULL, NULL, NULL}, + [3] = {{&machine_hard_i2c_type}, I2C4, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, #endif }; @@ -147,26 +139,18 @@ int machine_hard_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, m typedef mp_machine_soft_i2c_obj_t machine_hard_i2c_obj_t; -STATIC machine_hard_i2c_obj_t machine_hard_i2c_obj[] = { +STATIC machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = { #if defined(MICROPY_HW_I2C1_SCL) - {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, - #else - {{NULL}, 0, 0, NULL, NULL}, + [0] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA}, #endif #if defined(MICROPY_HW_I2C2_SCL) - {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, - #else - {{NULL}, 0, 0, NULL, NULL}, + [1] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA}, #endif #if defined(MICROPY_HW_I2C3_SCL) - {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, - #else - {{NULL}, 0, 0, NULL, NULL}, + [2] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA}, #endif #if defined(MICROPY_HW_I2C4_SCL) - {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, - #else - {{NULL}, 0, 0, NULL, NULL}, + [3] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA}, #endif }; diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index f3a3d48e7f321..b9fa3833ecafd 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -180,6 +180,7 @@ #define MP_HAL_UNIQUE_ID_ADDRESS (0x1ff1e800) #define PYB_EXTI_NUM_VECTORS (24) +#define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) @@ -188,6 +189,7 @@ #define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7590) #define PYB_EXTI_NUM_VECTORS (23) +#define MICROPY_HW_MAX_I2C (4) #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (6) From c769da1aaa28fb0eba9fabfba84c39cbc09e23da Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 21 May 2019 13:45:17 +1000 Subject: [PATCH 0099/1299] stm32/i2c: Support setting the I2C TIMINGR value via keyword arg. On MCUs that have an I2C TIMINGR register, this can now be explicitly set via the "timingr" keyword argument to the I2C constructor, for both machine.I2C and pyb.I2C. This allows to configure precise timing values when the defaults are inadequate. --- ports/stm32/machine_i2c.c | 18 +++++++++++++++++- ports/stm32/pyb_i2c.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 2aebb9426e63b..b423ec1c8c216 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -187,15 +187,24 @@ STATIC void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, u /******************************************************************************/ /* MicroPython bindings for machine API */ +#if defined(STM32F0) || defined(STM32F7) +#define MACHINE_I2C_TIMINGR (1) +#else +#define MACHINE_I2C_TIMINGR (0) +#endif + mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { // parse args - enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout }; + enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout, ARG_timingr }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_POLL_DEFAULT_TIMEOUT_US} }, + #if MACHINE_I2C_TIMINGR + { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + #endif }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -241,6 +250,13 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz // initialise the I2C peripheral machine_hard_i2c_init(self, args[ARG_freq].u_int, args[ARG_timeout].u_int); + #if MACHINE_I2C_TIMINGR + // If given, explicitly set the TIMINGR value + if (args[ARG_timingr].u_obj != mp_const_none) { + self->i2c->TIMINGR = mp_obj_get_int_truncated(args[ARG_timingr].u_obj); + } + #endif + return MP_OBJ_FROM_PTR(self); } diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 233cbba512f40..8b816a25b135e 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -135,6 +135,8 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = { // The STM32F0, F3, F7, H7 and L4 use a TIMINGR register rather than ClockSpeed and // DutyCycle. +#define PYB_I2C_TIMINGR (1) + #if defined(STM32F746xx) // The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant @@ -213,6 +215,8 @@ uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c) { #else +#define PYB_I2C_TIMINGR (0) + #define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL) #define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FULL) @@ -564,7 +568,15 @@ STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki mp_printf(print, "I2C(%u)", i2c_num); } else { if (in_master_mode(self)) { - mp_printf(print, "I2C(%u, I2C.MASTER, baudrate=%u)", i2c_num, pyb_i2c_get_baudrate(self->i2c)); + mp_printf(print, "I2C(%u, I2C.MASTER, baudrate=%u" + #if PYB_I2C_TIMINGR + ", timingr=0x%08x" + #endif + ")", i2c_num, pyb_i2c_get_baudrate(self->i2c) + #if PYB_I2C_TIMINGR + , self->i2c->Init.Timing + #endif + ); } else { mp_printf(print, "I2C(%u, I2C.SLAVE, addr=0x%02x)", i2c_num, (self->i2c->Instance->OAR1 >> 1) & 0x7f); } @@ -586,6 +598,9 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, co { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_HW_I2C_BAUDRATE_DEFAULT} }, { MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_dma, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + #if PYB_I2C_TIMINGR + { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + #endif }; // parse args @@ -602,7 +617,16 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, co init->OwnAddress1 = (args[1].u_int << 1) & 0xfe; } - i2c_set_baudrate(init, MIN(args[2].u_int, MICROPY_HW_I2C_BAUDRATE_MAX)); + // Set baudrate or timing value (if supported) + #if PYB_I2C_TIMINGR + if (args[5].u_obj != mp_const_none) { + init->Timing = mp_obj_get_int_truncated(args[5].u_obj); + } else + #endif + { + i2c_set_baudrate(init, MIN(args[2].u_int, MICROPY_HW_I2C_BAUDRATE_MAX)); + } + init->AddressingMode = I2C_ADDRESSINGMODE_7BIT; init->DualAddressMode = I2C_DUALADDRESS_DISABLED; init->GeneralCallMode = args[3].u_bool ? I2C_GENERALCALL_ENABLED : I2C_GENERALCALL_DISABLED; From fb54736bdb5c01a4051a77c8b048502c6a41e044 Mon Sep 17 00:00:00 2001 From: stijn Date: Mon, 20 May 2019 10:35:31 +0200 Subject: [PATCH 0100/1299] py/objarray: Add decode method to bytearray. Reuse the implementation for bytes since it works the same way regardless of the underlying type. This method gets added for CPython compatibility of bytearray, but to keep the code simple and small array.array now also has a working decode method, which is non-standard but doesn't hurt. --- py/objarray.c | 3 +++ py/objstr.h | 1 + tests/basics/bytearray_decode.py | 6 ++++++ 3 files changed, 10 insertions(+) create mode 100644 tests/basics/bytearray_decode.py diff --git a/py/objarray.c b/py/objarray.c index 89d2f21806875..4e58d8e5daa6d 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -530,6 +530,9 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui STATIC const mp_rom_map_elem_t array_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&array_append_obj) }, { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&array_extend_obj) }, + #if MICROPY_CPYTHON_COMPAT + { MP_ROM_QSTR(MP_QSTR_decode), MP_ROM_PTR(&bytes_decode_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table); diff --git a/py/objstr.h b/py/objstr.h index a10d0df8bed14..15ed7a2256015 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -102,5 +102,6 @@ MP_DECLARE_CONST_FUN_OBJ_1(str_isalpha_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_isdigit_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj); MP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj); #endif // MICROPY_INCLUDED_PY_OBJSTR_H diff --git a/tests/basics/bytearray_decode.py b/tests/basics/bytearray_decode.py new file mode 100644 index 0000000000000..b5e1cb419bda7 --- /dev/null +++ b/tests/basics/bytearray_decode.py @@ -0,0 +1,6 @@ +try: + print(bytearray(b'').decode()) + print(bytearray(b'abc').decode()) +except AttributeError: + print("SKIP") + raise SystemExit From c03f81c633ace3c563f5ace2e906737e98b259d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rinsoz?= Date: Mon, 20 May 2019 18:47:23 +0200 Subject: [PATCH 0101/1299] py: Update makefiles to use $(CAT) variable instead of hard coded "cat". The variable $(CAT) is initialised with the "cat" value in mkenv.mk like for the other command line tools (rm, echo, cp, mkdir etc). With this, for example, Windows users can specify the path of cat.exe. --- py/mkenv.mk | 1 + py/py.mk | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/py/mkenv.mk b/py/mkenv.mk index 87e92ec6f9d6b..04e7acc1bfc9b 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -42,6 +42,7 @@ ECHO = @echo CP = cp MKDIR = mkdir SED = sed +CAT = cat PYTHON = python3 AS = $(CROSS_COMPILE)as diff --git a/py/py.mk b/py/py.mk index 0fbc9f14bbe3c..3d8d849e2b57f 100644 --- a/py/py.mk +++ b/py/py.mk @@ -338,7 +338,7 @@ MPCONFIGPORT_MK = $(wildcard mpconfigport.mk) # the lines in "" and then unwrap after the preprocessor is finished. $(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) $(PY_SRC)/makeqstrdata.py mpconfigport.h $(MPCONFIGPORT_MK) $(PY_SRC)/mpconfig.h | $(HEADER_BUILD) $(ECHO) "GEN $@" - $(Q)cat $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | $(SED) 's/^"\(Q(.*)\)"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h + $(Q)$(CAT) $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | $(SED) 's/^\"\(Q(.*)\)\"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h $(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@ # build a list of registered modules for py/objmodule.c. From 85bde0889da8cc3315a3c96ff6933ca19e356569 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Tue, 21 May 2019 17:44:58 +0200 Subject: [PATCH 0102/1299] lib/nrfx: Upgrade nrfx to master. Updating the nrfx git submodule containing HAL drivers for nrf-port from v1.3.1 to current master. The version pointed to is one commit ahead of v1.7.1 release. The extra commit contains a bugfix for nrfx_uart_tx_in_progress() making it report correctly. The general upgrade of nrfx is considered to be safe, as almost all changes in between 1.3.1 and 1.7.1 are related to peripherals and target devices not used by the nrf-port as of today. --- lib/nrfx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nrfx b/lib/nrfx index d4ebe15f58de1..7513fc9d5c10d 160000 --- a/lib/nrfx +++ b/lib/nrfx @@ -1 +1 @@ -Subproject commit d4ebe15f58de1442e3eed93b40d13930e7785903 +Subproject commit 7513fc9d5c10dc28b25bf2bb6ff0ba66cb2a3c3d From d80abd035e209b8fcc399b142352a49702f701fc Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Tue, 21 May 2019 18:18:44 +0200 Subject: [PATCH 0103/1299] nrf/nrfx_glue: Adapt to nrfx v.1.7.1. Defining NRFX_STATIC_ASSERT macro to be empty, but available to nrfx. --- ports/nrf/nrfx_glue.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/nrf/nrfx_glue.h b/ports/nrf/nrfx_glue.h index 0108e3242fd19..316e02df1d54c 100644 --- a/ports/nrf/nrfx_glue.h +++ b/ports/nrf/nrfx_glue.h @@ -29,6 +29,8 @@ #include +#define NRFX_STATIC_ASSERT(expression) + #define NRFX_ASSERT(expression) do { bool res = expression; (void)res; } while (0) #define NRFX_DELAY_US mp_hal_delay_us From 302ffdba7f06e8827532834b5902406cd7bf4ea0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 May 2019 12:35:33 +1000 Subject: [PATCH 0104/1299] nrf/uart: Change UART driver to be non-blocking and use IRQs. As part of this, ctrl-C is now able to interrupt a running program. --- ports/nrf/modules/machine/uart.c | 55 ++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index cef98fb07ffc2..95921c055dd76 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -35,8 +35,10 @@ #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" +#include "py/ringbuf.h" #include "pin.h" #include "genhdr/pins.h" +#include "lib/utils/interrupt_char.h" #include "uart.h" #include "mpconfigboard.h" @@ -47,15 +49,25 @@ #if MICROPY_PY_MACHINE_UART +typedef struct _machine_hard_uart_buf_t { + uint8_t tx_buf[1]; + uint8_t rx_buf[1]; + uint8_t rx_ringbuf_array[64]; + volatile ringbuf_t rx_ringbuf; +} machine_hard_uart_buf_t; + typedef struct _machine_hard_uart_obj_t { mp_obj_base_t base; const nrfx_uart_t * p_uart; // Driver instance + machine_hard_uart_buf_t *buf; } machine_hard_uart_obj_t; static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0); +STATIC machine_hard_uart_buf_t machine_hard_uart_buf[1]; + STATIC const machine_hard_uart_obj_t machine_hard_uart_obj[] = { - {{&machine_hard_uart_type}, .p_uart = &instance0}, + {{&machine_hard_uart_type}, .p_uart = &instance0, .buf = &machine_hard_uart_buf[0]}, }; void uart_init0(void) { @@ -70,27 +82,36 @@ STATIC int uart_find(mp_obj_t id) { mp_raise_ValueError("UART doesn't exist"); } -void uart_irq_handler(mp_uint_t uart_id) { - +STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context) { + machine_hard_uart_obj_t *self = p_context; + if (p_event->type == NRFX_UART_EVT_RX_DONE) { + int chr = self->buf->rx_buf[0]; + nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); + #if !MICROPY_PY_BLE_NUS && MICROPY_KBD_EXCEPTION + if (chr == mp_interrupt_char) { + mp_keyboard_interrupt(); + } else + #endif + { + ringbuf_put((ringbuf_t*)&self->buf->rx_ringbuf, chr); + } + } } -bool uart_rx_any(const machine_hard_uart_obj_t *uart_obj) { - // TODO: uart will block for now. - return true; +bool uart_rx_any(const machine_hard_uart_obj_t *self) { + return self->buf->rx_ringbuf.iput != self->buf->rx_ringbuf.iget; } int uart_rx_char(const machine_hard_uart_obj_t * self) { - uint8_t ch; - nrfx_uart_rx(self->p_uart, &ch, 1); - return (int)ch; + return ringbuf_get((ringbuf_t*)&self->buf->rx_ringbuf); } STATIC nrfx_err_t uart_tx_char(const machine_hard_uart_obj_t * self, int c) { while (nrfx_uart_tx_in_progress(self->p_uart)) { ; } - - return nrfx_uart_tx(self->p_uart, (uint8_t *)&c, 1); + self->buf->tx_buf[0] = c; + return nrfx_uart_tx(self->p_uart, &self->buf->tx_buf[0], 1); } @@ -181,9 +202,15 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a // Set context to this instance of UART config.p_context = (void *)self; - // Set NULL as callback function to keep it blocking - nrfx_uart_init(self->p_uart, &config, NULL); + // Initialise ring buffer + self->buf->rx_ringbuf.buf = self->buf->rx_ringbuf_array; + self->buf->rx_ringbuf.size = sizeof(self->buf->rx_ringbuf_array); + self->buf->rx_ringbuf.iget = 0; + self->buf->rx_ringbuf.iput = 0; + // Enable event callback and start asynchronous receive + nrfx_uart_init(self->p_uart, &config, uart_event_handler); + nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); nrfx_uart_rx_enable(self->p_uart); return MP_OBJ_FROM_PTR(self); @@ -250,6 +277,8 @@ STATIC mp_uint_t machine_hard_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_ // read the data for (size_t i = 0; i < size; i++) { + while (!uart_rx_any(self)) { + } buf[i] = uart_rx_char(self); } From 50d5114fcd5f3b81d400c1297d0ce754c1dcd2e6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 3 May 2019 12:36:56 +1000 Subject: [PATCH 0105/1299] nrf/mpconfigport.h: Enable MICROPY_KBD_EXCEPTION by default. --- ports/nrf/mpconfigport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 0e3cf7b39d6ee..da9a03e1d03b5 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -47,7 +47,7 @@ #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_EMACS_KEYS (0) #define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_KBD_EXCEPTION (0) +#define MICROPY_KBD_EXCEPTION (1) #define MICROPY_ENABLE_SOURCE_LINE (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #if NRF51 From 456c89f7497d55e641e4374a1860ba08f3b84688 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 22 May 2019 12:45:27 +1000 Subject: [PATCH 0106/1299] nrf/uart: Make UART print output something, and add write method. --- ports/nrf/modules/machine/uart.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index 95921c055dd76..b9c018fc84168 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -134,10 +134,9 @@ void uart_tx_strn_cooked(const machine_hard_uart_obj_t *uart_obj, const char *st /* MicroPython bindings */ STATIC void machine_hard_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_printf(print, "UART(0)"); } - - /// \method init(id, baudrate) /// /// Initialise the UART bus with the given parameters: @@ -251,13 +250,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_sendbreak_obj, machine_hard_u STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = { // instance methods - /// \method read([nbytes]) { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - /// \method readline() { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - /// \method readinto(buf[, nbytes]) { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - /// \method writechar(buf) + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_hard_uart_writechar_obj) }, { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_hard_uart_readchar_obj) }, { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_hard_uart_sendbreak_obj) }, From 9cf1cbb0575387d79b496b6ff14736ca9239c0a1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 22 May 2019 12:46:09 +1000 Subject: [PATCH 0107/1299] nrf/mphalport: Use wfi to save power while waiting at the UART REPL. --- ports/nrf/mphalport.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 9ce904514ecc6..a050df147087c 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -58,6 +58,7 @@ int mp_hal_stdin_rx_chr(void) { if (MP_STATE_PORT(board_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(board_stdio_uart))) { return uart_rx_char(MP_STATE_PORT(board_stdio_uart)); } + __WFI(); } return 0; From a4f4239e9589c49ff621a76cd860ca6fa6b7efe4 Mon Sep 17 00:00:00 2001 From: Sebastien Rinsoz Date: Tue, 21 May 2019 11:35:09 +0200 Subject: [PATCH 0108/1299] py: Update makefiles to use $(TOUCH) instead of hard coded "touch". The variable $(TOUCH) is initialized with the "touch" value in mkenv.mk like for the other command line tools (rm, echo, cp, mkdir etc). With this, for example, Windows users can specify the path of touch.exe. --- py/mkenv.mk | 1 + py/mkrules.mk | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/py/mkenv.mk b/py/mkenv.mk index 04e7acc1bfc9b..46eedf988ab5d 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -43,6 +43,7 @@ CP = cp MKDIR = mkdir SED = sed CAT = cat +TOUCH = touch PYTHON = python3 AS = $(CROSS_COMPILE)as diff --git a/py/mkrules.mk b/py/mkrules.mk index caa9527c70bc6..3f310c19582a3 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -77,7 +77,7 @@ $(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_ $(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last $(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makeqstrdefs.py split $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED) - $(Q)touch $@ + $(Q)$(TOUCH) $@ $(QSTR_DEFS_COLLECTED): $(HEADER_BUILD)/qstr.split $(ECHO) "GEN $@" @@ -190,7 +190,7 @@ print-cfg: print-def: @$(ECHO) "The following defines are built into the $(CC) compiler" - touch __empty__.c + $(TOUCH) __empty__.c @$(CC) -E -Wp,-dM __empty__.c @$(RM) -f __empty__.c From 6cf4e9675b11de43fe99844919670ba0c3ff544a Mon Sep 17 00:00:00 2001 From: Sebastien Rinsoz Date: Tue, 21 May 2019 14:27:05 +0200 Subject: [PATCH 0109/1299] py/mkrules.mk: Remove unnecessary ; in makefile. This ; make Windows compilation fail with GNU makefile 4.2.1. It was added in 0dc85c9f86735c35cf14555482b2c8923cf31a6a as part of a shell if- statement, but this if-statement was subsequently removed in 23a693ec2d8c2a194f61482dc0e1adb070fb6ad4 so the semicolon is not needed. --- py/mkrules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 3f310c19582a3..4e4fdef55c62d 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -72,7 +72,7 @@ $(OBJ): | $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/mpversion.h # - else, process all source files ($^) [this covers "make -B" which can set $? to empty] $(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h $(ECHO) "GEN $@" - $(Q)$(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) >$(HEADER_BUILD)/qstr.i.last; + $(Q)$(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) >$(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last $(ECHO) "GEN $@" From 4f4477872861927f7d9230248dcf43d15bc7b57c Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 23 May 2019 13:55:19 +1000 Subject: [PATCH 0110/1299] stm32/sdcard: Add switch break to ensure only correct SD/MMC IRQ is run. --- ports/stm32/sdcard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 16e6506156fdd..8ffba0b4c5c9d 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -370,10 +370,12 @@ STATIC void sdmmc_irq_handler(void) { #if MICROPY_HW_ENABLE_SDCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_SD: HAL_SD_IRQHandler(&sdmmc_handle.sd); + break; #endif #if MICROPY_HW_ENABLE_MMCARD case PYB_SDMMC_FLAG_ACTIVE | PYB_SDMMC_FLAG_MMC: HAL_MMC_IRQHandler(&sdmmc_handle.mmc); + break; #endif } } From 2762f323bf6407093dc814591e7c6d08ca82bc6f Mon Sep 17 00:00:00 2001 From: stijn Date: Thu, 21 Jun 2018 11:54:49 +0200 Subject: [PATCH 0111/1299] windows: Fix line wrapping behaviour on the REPL. This enables going back to previous wrapped lines using backspace or left arrow: instead of just sticking to the beginning of a line, the cursor will move a line up. --- ports/windows/windows_mphal.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ports/windows/windows_mphal.c b/ports/windows/windows_mphal.c index 153b044235434..1e3a09291060e 100644 --- a/ports/windows/windows_mphal.c +++ b/ports/windows/windows_mphal.c @@ -106,12 +106,23 @@ void mp_hal_set_interrupt_char(char c) { } void mp_hal_move_cursor_back(uint pos) { + if (!pos) { + return; + } assure_conout_handle(); CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(con_out, &info); info.dwCursorPosition.X -= (short)pos; - if (info.dwCursorPosition.X < 0) { + // Move up a line if needed. + while (info.dwCursorPosition.X < 0) { + info.dwCursorPosition.X = info.dwSize.X + info.dwCursorPosition.X; + info.dwCursorPosition.Y -= 1; + } + // Caller requested to move out of the screen. That's not possible so just clip, + // it's the caller's responsibility to not let this happen. + if (info.dwCursorPosition.Y < 0) { info.dwCursorPosition.X = 0; + info.dwCursorPosition.Y = 0; } SetConsoleCursorPosition(con_out, info.dwCursorPosition); } From c066dadc5b91d000e2f7bba9f3e3edbf0bf33a3d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 24 May 2019 14:51:48 +1000 Subject: [PATCH 0112/1299] mpy-cross/mpconfigport.h: Remove defn of MP_NOINLINE to use global one. A global definition of MP_NOINLINE was added to py/mpconfig.h long ago in 0f5bf1aafe0ca073d958f271bd96addc6da8fe10 --- mpy-cross/mpconfigport.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index 6aa013a134332..125303afd2992 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -112,10 +112,6 @@ typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) (void)0 -#ifndef MP_NOINLINE -#define MP_NOINLINE __attribute__((noinline)) -#endif - // We need to provide a declaration/definition of alloca() #ifdef __FreeBSD__ #include From b88bf42793d7469acaeb8b9bd279c0a8c9d20558 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 28 Mar 2019 16:12:20 +0200 Subject: [PATCH 0113/1299] zephyr/README: Reorder content related to recently added I2C. So it fits better with existing narrative. --- ports/zephyr/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/zephyr/README.md b/ports/zephyr/README.md index 3d2e883adc166..6bcbccd8b36a3 100644 --- a/ports/zephyr/README.md +++ b/ports/zephyr/README.md @@ -12,8 +12,8 @@ Features supported at this time: * REPL (interactive prompt) over Zephyr UART console. * `utime` module for time measurements and delays. -* `machine.I2C` class for I2C control. * `machine.Pin` class for GPIO control. +* `machine.I2C` class for I2C control. * `usocket` module for networking (IPv4/IPv6). * "Frozen modules" support to allow to bundle Python modules together with firmware. Including complete applications, including with @@ -82,13 +82,6 @@ To blink an LED: LED.value(0) time.sleep(0.5) -To scan for I2C slaves: - - from machine import I2C - - i2c = I2C("I2C_0") - i2c.scan() - The above code uses an LED location for a FRDM-K64F board (port B, pin 21; following Zephyr conventions port are identified by "GPIO_x", where *x* starts from 0). You will need to adjust it for another board (using board's @@ -96,6 +89,13 @@ reference materials). To execute the above sample, copy it to clipboard, in MicroPython REPL enter "paste mode" using Ctrl+E, paste clipboard, press Ctrl+D to finish paste mode and start execution. +Example of using I2C to scan for I2C slaves: + + from machine import I2C + + i2c = I2C("I2C_0") + i2c.scan() + Minimal build ------------- From c4a6d9c631a3e529aeedeaf5c24fa1bd748d493f Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 28 Mar 2019 16:15:42 +0200 Subject: [PATCH 0114/1299] zephyr: Switch back to enabling I2C in board-specific configs. I2C can't be enabled in prj_base.conf because it's a board-specific feature. For example, if a board doesn't have I2C but CONFIG_I2C=y then the build will fail (on Zephyr build system side). The patch here gets the qemu_cortex_m3 build working again. --- ports/zephyr/prj_base.conf | 3 --- ports/zephyr/prj_frdm_k64f.conf | 3 +++ ports/zephyr/prj_frdm_kw41z.conf | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ports/zephyr/prj_base.conf b/ports/zephyr/prj_base.conf index 58206a0bc2aab..993dfdc26f9ec 100644 --- a/ports/zephyr/prj_base.conf +++ b/ports/zephyr/prj_base.conf @@ -14,9 +14,6 @@ CONFIG_NEWLIB_LIBC=y CONFIG_FLOAT=y CONFIG_MAIN_STACK_SIZE=4736 -# Drivers -CONFIG_I2C=y - # Enable sensor subsystem (doesn't add code if not used). # Specific sensors should be enabled per-board. CONFIG_SENSOR=y diff --git a/ports/zephyr/prj_frdm_k64f.conf b/ports/zephyr/prj_frdm_k64f.conf index 477f3b8257f82..c2166c00df4e7 100644 --- a/ports/zephyr/prj_frdm_k64f.conf +++ b/ports/zephyr/prj_frdm_k64f.conf @@ -1,6 +1,9 @@ # Networking drivers CONFIG_NET_L2_ETHERNET=y +# Hardware features +CONFIG_I2C=y + # Sensor drivers CONFIG_FXOS8700=y CONFIG_FXOS8700_MODE_HYBRID=y diff --git a/ports/zephyr/prj_frdm_kw41z.conf b/ports/zephyr/prj_frdm_kw41z.conf index 486ece2bd8e01..ff7b7887e161d 100644 --- a/ports/zephyr/prj_frdm_kw41z.conf +++ b/ports/zephyr/prj_frdm_kw41z.conf @@ -1,3 +1,6 @@ +# Hardware features +CONFIG_I2C=y + # Sensor drivers CONFIG_FXOS8700=y CONFIG_FXOS8700_MODE_HYBRID=y From 5357dad52efbe5773f4beda7ad014dc62ad8e44f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 22 May 2019 15:05:03 +1000 Subject: [PATCH 0115/1299] esp8266: Fix ticks_ms to correctly handle wraparound of system counter. Fixes issue #4795. --- ports/esp8266/esp_mphal.c | 4 +++- ports/esp8266/ets_alt_task.c | 23 ++++++++++++++--------- ports/esp8266/ets_alt_task.h | 2 ++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c index df97a73430235..351bf522c8295 100644 --- a/ports/esp8266/esp_mphal.c +++ b/ports/esp8266/esp_mphal.c @@ -120,7 +120,9 @@ void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) { } uint32_t mp_hal_ticks_ms(void) { - return ((uint64_t)system_time_high_word << 32 | (uint64_t)system_get_time()) / 1000; + // Compute milliseconds from 64-bit microsecond counter + system_time_update(); + return ((uint64_t)system_time_high_word << 32 | (uint64_t)system_time_low_word) / 1000; } uint32_t mp_hal_ticks_us(void) { diff --git a/ports/esp8266/ets_alt_task.c b/ports/esp8266/ets_alt_task.c index b724b8f14a183..0b1615d6580ea 100644 --- a/ports/esp8266/ets_alt_task.c +++ b/ports/esp8266/ets_alt_task.c @@ -112,22 +112,27 @@ int ets_loop_iter_disable = 0; int ets_loop_dont_feed_sw_wdt = 0; // to implement a 64-bit wide microsecond counter -static uint32_t system_time_prev = 0; +uint32_t system_time_low_word = 0; uint32_t system_time_high_word = 0; -bool ets_loop_iter(void) { - if (ets_loop_iter_disable) { - return false; - } - - // handle overflow of system microsecond counter +void system_time_update(void) { + // Handle overflow of system microsecond counter ets_intr_lock(); uint32_t system_time_cur = system_get_time(); - if (system_time_cur < system_time_prev) { + if (system_time_cur < system_time_low_word) { system_time_high_word += 1; // record overflow of low 32-bits } - system_time_prev = system_time_cur; + system_time_low_word = system_time_cur; ets_intr_unlock(); +} + +bool ets_loop_iter(void) { + if (ets_loop_iter_disable) { + return false; + } + + // Update 64-bit microsecond counter + system_time_update(); // 6 words before pend_flag_noise_check is a variable that is used by // the software WDT. A 1.6 second period timer will increment this diff --git a/ports/esp8266/ets_alt_task.h b/ports/esp8266/ets_alt_task.h index e7a15c3ad57f5..7eb8ff3a54816 100644 --- a/ports/esp8266/ets_alt_task.h +++ b/ports/esp8266/ets_alt_task.h @@ -3,8 +3,10 @@ extern int ets_loop_iter_disable; extern int ets_loop_dont_feed_sw_wdt; +extern uint32_t system_time_low_word; extern uint32_t system_time_high_word; +void system_time_update(void); bool ets_loop_iter(void); #endif // MICROPY_INCLUDED_ESP8266_ETS_ALT_TASK_H From 1470184bddcdb7f325a42a25ad76b8cd3714606f Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 2 May 2019 15:59:38 +1000 Subject: [PATCH 0116/1299] stm32/sdram: Update MPU settings to block invalid region, change attrs. Set the active MPU region to the actual size of SDRAM configured and invalidate the rest of the memory-mapped region, to prevent errors due to CPU speculation. Also update the attributes of the SDRAM region as per ST recommendations, and change region numbers to avoid conflicts elsewhere in the codebase (see eth usage). --- ports/stm32/sdram.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index e2b29c56e2166..b3c5bbeeed9b6 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -39,6 +39,13 @@ #define SDRAM_START_ADDRESS 0xD0000000 #endif +// Provides the MPU_REGION_SIZE_X value when passed the size of region in bytes +// "m" must be a power of 2 between 32 and 4G (2**5 and 2**32) and this formula +// computes the log2 of "m", minus 1 +#define MPU_REGION_SIZE(m) (((m) - 1) / (((m) - 1) % 255 + 1) / 255 % 255 * 8 + 7 - 86 / (((m) - 1) % 255 + 12) - 1) + +#define SDRAM_MPU_REGION_SIZE (MPU_REGION_SIZE(MICROPY_HW_SDRAM_SIZE)) + #ifdef FMC_SDRAM_BANK static void sdram_init_seq(SDRAM_HandleTypeDef @@ -244,17 +251,33 @@ static void sdram_init_seq(SDRAM_HandleTypeDef /* Disable the MPU */ HAL_MPU_Disable(); - /* Configure the MPU attributes as Write-Through for External SDRAM */ + /* Configure the MPU attributes for External SDRAM + Initially disable all access for the entire SDRAM memory space, + then enable access/caching for the size used + */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER4; MPU_InitStruct.BaseAddress = SDRAM_START_ADDRESS; - MPU_InitStruct.Size = MPU_REGION_SIZE_256MB; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.Size = MPU_REGION_SIZE_512MB; + MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER5; + MPU_InitStruct.BaseAddress = SDRAM_START_ADDRESS; + MPU_InitStruct.Size = SDRAM_MPU_REGION_SIZE; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); From ab265537593ed10d075c2b8ea8b5e0b193c13094 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 27 May 2019 11:55:40 +1000 Subject: [PATCH 0117/1299] py/vm: Remove obsolete comments about matching of exception opcodes. These are incorrect since 5a2599d96299ad37cda954f1de345159f9acf11c --- py/vm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/py/vm.c b/py/vm.c index 901a23f225f05..260a7f38baf9d 100644 --- a/py/vm.c +++ b/py/vm.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014-2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -675,7 +675,6 @@ unwind_jump:; DISPATCH_WITH_PEND_EXC_CHECK(); } - // matched against: POP_BLOCK or POP_EXCEPT (anything else?) ENTRY(MP_BC_SETUP_EXCEPT): ENTRY(MP_BC_SETUP_FINALLY): { MARK_EXC_IP_SELECTIVE(); @@ -758,7 +757,6 @@ unwind_jump:; DISPATCH(); } - // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH ENTRY(MP_BC_POP_EXCEPT_JUMP): { assert(exc_sp >= exc_stack); POP_EXC_BLOCK(); From 887a6712c2a302bd0bdeceb8ee9bc33a6de64dae Mon Sep 17 00:00:00 2001 From: Tom Manning Date: Wed, 15 May 2019 05:50:53 -0400 Subject: [PATCH 0118/1299] esp32/machine_touchpad: Use HW timer for FSM to enable wake-on-touch. --- ports/esp32/machine_touchpad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/machine_touchpad.c b/ports/esp32/machine_touchpad.c index 96de1a2a1d74a..dd36bdd7645f2 100644 --- a/ports/esp32/machine_touchpad.c +++ b/ports/esp32/machine_touchpad.c @@ -69,6 +69,7 @@ STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ static int initialized = 0; if (!initialized) { touch_pad_init(); + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); initialized = 1; } esp_err_t err = touch_pad_config(self->touchpad_id, 0); From 8c9758ff2ee5c5b70e4eab5fe0396de2e21299b0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 28 May 2019 17:22:54 +1000 Subject: [PATCH 0119/1299] unix/modusocket: Raise ETIMEDOUT when connect or accept has timeout. --- ports/unix/modusocket.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 8cbd3d077d2a9..9b82378bb4b35 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -160,7 +160,12 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); - RAISE_ERRNO(r, errno); + int err = errno; + if (r == -1 && self->blocking && err == EINPROGRESS) { + // EINPROGRESS on a blocking socket means the operation timed out + err = MP_ETIMEDOUT; + } + RAISE_ERRNO(r, err); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); @@ -190,7 +195,12 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { byte addr[32]; socklen_t addr_len = sizeof(addr); int fd = accept(self->fd, (struct sockaddr*)&addr, &addr_len); - RAISE_ERRNO(fd, errno); + int err = errno; + if (fd == -1 && self->blocking && err == EAGAIN) { + // EAGAIN on a blocking socket means the operation timed out + err = MP_ETIMEDOUT; + } + RAISE_ERRNO(fd, err); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); t->items[0] = MP_OBJ_FROM_PTR(socket_new(fd)); From 883e987b90e82f0a9ab223910890da2c5d50b9d3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 28 May 2019 17:43:00 +1000 Subject: [PATCH 0120/1299] esp32/modsocket: Raise EAGAIN when accept fails in non-blocking mode. EAGAIN should be for pure non-blocking mode and ETIMEDOUT for when there is a finite (but non-zero) timeout enabled. --- ports/esp32/modsocket.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index 1d7aec5efa2a2..8b80e631dbbf2 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -253,7 +253,13 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { if (errno != EAGAIN) exception_from_errno(errno); check_for_exceptions(); } - if (new_fd < 0) mp_raise_OSError(MP_ETIMEDOUT); + if (new_fd < 0) { + if (self->retries == 0) { + mp_raise_OSError(MP_EAGAIN); + } else { + mp_raise_OSError(MP_ETIMEDOUT); + } + } // create new socket object socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t); From 734ada3e2980d1bbf5c7a1ea5c624b34be16dfa9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 01:24:43 +1000 Subject: [PATCH 0121/1299] extmod/modlwip: Free any incoming bufs/connections before closing PCB. Commit 2848a613ac61fce209962354c2698ee587a2c26a introduced a bug where lwip_socket_free_incoming() accessed pcb.tcp->state after the PCB was closed. The state may have changed due to that close call, or the PCB may be freed and therefore invalid. This commit fixes that by calling lwip_socket_free_incoming() before the PCB is closed. --- extmod/modlwip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index e0bf17db8c4e2..06ed764b53cdf 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1416,6 +1416,9 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ tcp_err(socket->pcb.tcp, NULL); tcp_recv(socket->pcb.tcp, NULL); + // Free any incoming buffers or connections that are stored + lwip_socket_free_incoming(socket); + switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { if (tcp_close(socket->pcb.tcp) != ERR_OK) { @@ -1430,7 +1433,7 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break; //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; } - lwip_socket_free_incoming(socket); + socket->pcb.tcp = NULL; socket->state = _ERR_BADF; ret = 0; From 019dd84af1e8e9bbdbbb6377c28950d31f05a77c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 01:29:48 +1000 Subject: [PATCH 0122/1299] extmod/modlwip: Register TCP close-timeout callback before closing PCB. In d5f0c87bb985ae344014dc2041fbaad5c522f638 this call to tcp_poll() was added to put a timeout on closing TCP sockets. But after calling tcp_close() the PCB may be freed and therefore invalid, so tcp_poll() can not be used at that point. As a fix this commit calls tcp_poll() before closing the TCP PCB. If the PCB is subsequently closed and freed by tcp_close() or tcp_abort() then the PCB will not be on any active list and the callback will not be executed, which is the desired behaviour (the _lwip_tcp_close_poll() callback only needs to be called if the PCB remains active for longer than the timeout). --- extmod/modlwip.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 06ed764b53cdf..4127d21addea5 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1421,12 +1421,15 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { + if (socket->pcb.tcp->state != LISTEN) { + // Schedule a callback to abort the connection if it's not cleanly closed after + // the given timeout. The callback must be set before calling tcp_close since + // the latter may free the pcb; if it doesn't then the callback will be active. + tcp_poll(socket->pcb.tcp, _lwip_tcp_close_poll, MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS / 500); + } if (tcp_close(socket->pcb.tcp) != ERR_OK) { DEBUG_printf("lwip_close: had to call tcp_abort()\n"); tcp_abort(socket->pcb.tcp); - } else { - // If connection not cleanly closed after timeout then abort the connection - tcp_poll(socket->pcb.tcp, _lwip_tcp_close_poll, MICROPY_PY_LWIP_TCP_CLOSE_TIMEOUT_MS / 500); } break; } From 66bcb5596aae3e2f7748ae6b2379e5c542647052 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 29 May 2019 11:11:20 +1000 Subject: [PATCH 0123/1299] stm32/modmachine: In bootloader() disable caches before reset of periphs Otherwise flushing and disabling the D-cache will give a hard-fault when SDRAM is used. Fixes #4818. --- ports/stm32/modmachine.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 7031dea91ca15..eca8322eac4ca 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -265,6 +265,12 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) storage_flush(); #endif + #if __DCACHE_PRESENT == 1 + // Flush and disable caches before turning off peripherals (eg SDRAM) + SCB_DisableICache(); + SCB_DisableDCache(); + #endif + HAL_RCC_DeInit(); HAL_DeInit(); @@ -276,10 +282,6 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) #if MICROPY_HW_USES_BOOTLOADER if (n_args == 0 || !mp_obj_is_true(args[0])) { // By default, with no args given, we enter the custom bootloader (mboot) - #if __DCACHE_PRESENT == 1 - SCB_DisableICache(); - SCB_DisableDCache(); - #endif branch_to_bootloader(0x70ad0000, 0x08000000); } @@ -289,10 +291,6 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) const char *data = mp_obj_str_get_data(args[0], &len); void *mboot_region = (void*)*((volatile uint32_t*)0x08000000); memmove(mboot_region, data, len); - #if __DCACHE_PRESENT == 1 - SCB_DisableICache(); - SCB_DisableDCache(); - #endif branch_to_bootloader(0x70ad0080, 0x08000000); } #endif From 0bb6b63e662fa688e448e41e4bafe0c146568e78 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 16:26:02 +1000 Subject: [PATCH 0124/1299] stm32/mboot/README: Fix some typos, describe bootloader and fwupdate.py. --- ports/stm32/mboot/README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ports/stm32/mboot/README.md b/ports/stm32/mboot/README.md index 14bfc66f9cd53..3128307b1edb9 100644 --- a/ports/stm32/mboot/README.md +++ b/ports/stm32/mboot/README.md @@ -46,14 +46,14 @@ How to use This assumes that the board declares and defines the relevant SPI flash configuration structs, eg in the board-specific bdev.c file. The - `MBOOT_SPIFLASH2_LAYOUT` string will be seen by the USB DFU utility and + `MBOOT_SPIFLASH_LAYOUT` string will be seen by the USB DFU utility and must describe the SPI flash layout. Note that the number of pages in this layout description (the `64` above) cannot be larger than 99 (it must fit in two digits) so the reported page size (the `32Kg` above) must be made large enough so the number of pages fits in two digits. Alternatively the layout can specify multiple sections like `32*16Kg,32*16Kg`, in which case `MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE` - must be changed to `16 / 4` to match tho `16Kg` value. + must be changed to `16 / 4` to match the `16Kg` value. Mboot supports up to two external SPI flash devices. To configure the second one use the same configuration names as above but with @@ -115,6 +115,10 @@ The last element in the data sequence must be the end element: * END: type=1, len=0 +Note: MicroPython's `machine.bootloader()` function performs steps 1-4 +above, and also accepts an optional bytes argument as additional data to +pass through to Mboot. + Loading firmware from a filesystem ---------------------------------- @@ -130,6 +134,9 @@ are located and what filename to program. The elements to use are: The firmware to load must be a gzip'd DfuSe file (.dfu.gz). +The provided fwupdate.py script contains helper functions to call into Mboot +with the correct data, and also to update Mboot itself. + Example: Mboot on PYBv1.x ------------------------- From 2715f3b696da7dc3a2ad6cf8da898de341c863ee Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 16:28:20 +1000 Subject: [PATCH 0125/1299] LICENSE: Update year range in top-level license. --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index e3474e33dd81a..e6a54cf269947 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013, 2014 Damien P. George +Copyright (c) 2013-2019 Damien P. George Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 6f75c4f3cd393131579db70cdf0b35d1fe5b95ab Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 16:38:10 +1000 Subject: [PATCH 0126/1299] all: Bump version to 1.11. --- docs/conf.py | 2 +- py/mpconfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 61c660aa667ce..71e561c9c00b0 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -74,7 +74,7 @@ # # We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags" # breakdown, so use the same version identifier for both to avoid confusion. -version = release = '1.10' +version = release = '1.11' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/py/mpconfig.h b/py/mpconfig.h index 2d857d8f6dbed..219f8de44b206 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -28,7 +28,7 @@ // Current version of MicroPython #define MICROPY_VERSION_MAJOR 1 -#define MICROPY_VERSION_MINOR 10 +#define MICROPY_VERSION_MINOR 11 #define MICROPY_VERSION_MICRO 0 // Combined version as a 32-bit number for convenience From bff4e130099e2ec17478bb00f7eaa5d85fb763dc Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 21:14:24 +1000 Subject: [PATCH 0127/1299] py/nativeglue: Make private glue funs all static, remove commented code. --- py/nativeglue.c | 12 +++--------- py/runtime.h | 3 --- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/py/nativeglue.c b/py/nativeglue.c index c810f31e60f25..8f38ecd16e3c6 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -97,7 +97,7 @@ mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) { #if MICROPY_EMIT_NATIVE -mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { +STATIC mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { if (new_globals == NULL) { // Globals were the originally the same so don't restore them return NULL; @@ -113,13 +113,13 @@ mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { // wrapper that accepts n_args and n_kw in one argument // (native emitter can only pass at most 3 arguments to a function) -mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) { +STATIC mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) { return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args); } // wrapper that makes raise obj and raises it // END_FINALLY opcode requires that we don't raise if o==None -void mp_native_raise(mp_obj_t o) { +STATIC void mp_native_raise(mp_obj_t o) { if (o != MP_OBJ_NULL && o != mp_const_none) { nlr_raise(mp_make_raise_obj(o)); } @@ -245,10 +245,4 @@ const void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_native_yield_from, }; -/* -void mp_f_vector(mp_fun_kind_t fun_kind) { - (mp_f_table[fun_kind])(); -} -*/ - #endif // MICROPY_EMIT_NATIVE diff --git a/py/runtime.h b/py/runtime.h index 0eb15d4617322..1ac383ca71c59 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -172,9 +172,6 @@ NORETURN void mp_raise_recursion_depth(void); int mp_native_type_from_qstr(qstr qst); mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type); mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type); -mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals); -mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args); -void mp_native_raise(mp_obj_t o); #define mp_sys_path (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_path_obj))) #define mp_sys_argv (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_argv_obj))) From a4f1d82757b8e95c21a095c99b7c3f04ded88104 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 21:17:29 +1000 Subject: [PATCH 0128/1299] py/nativeglue: Remove dependency on mp_fun_table in dyn-compiler mode. mpy-cross uses MICROPY_DYNAMIC_COMPILER and MICROPY_EMIT_NATIVE but does not actually need to execute native functions, and does not need mp_fun_table. This commit makes it so mp_fun_table and all its entries are not built when MICROPY_DYNAMIC_COMPILER is enabled, significantly reducing the size of the mpy-cross executable and allowing it to be built on more machines/OS's. --- py/emitnative.c | 3 +++ py/mpconfig.h | 1 + py/nativeglue.c | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/py/emitnative.c b/py/emitnative.c index f123ecbb58b01..278cc21e78482 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -609,8 +609,11 @@ STATIC void emit_native_end_pass(emit_t *emit) { const_table_alloc += nqstr; } emit->const_table = m_new(mp_uint_t, const_table_alloc); + #if !MICROPY_DYNAMIC_COMPILER // Store mp_fun_table pointer just after qstrs + // (but in dynamic-compiler mode eliminate dependency on mp_fun_table) emit->const_table[nqstr] = (mp_uint_t)(uintptr_t)mp_fun_table; + #endif #if MICROPY_PERSISTENT_CODE_SAVE size_t qstr_link_alloc = emit->qstr_link_cur; diff --git a/py/mpconfig.h b/py/mpconfig.h index 219f8de44b206..4172e175b243d 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -338,6 +338,7 @@ #endif // Whether the compiler is dynamically configurable (ie at runtime) +// This will disable the ability to execute native/viper code #ifndef MICROPY_DYNAMIC_COMPILER #define MICROPY_DYNAMIC_COMPILER (0) #endif diff --git a/py/nativeglue.c b/py/nativeglue.c index 8f38ecd16e3c6..11d7a283a272c 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -95,7 +95,7 @@ mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) { #endif -#if MICROPY_EMIT_NATIVE +#if MICROPY_EMIT_NATIVE && !MICROPY_DYNAMIC_COMPILER STATIC mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { if (new_globals == NULL) { From 0c29502ad995cfacc3b11f26a135707a06b8c27d Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 18 May 2019 23:01:36 +1000 Subject: [PATCH 0129/1299] stm32/usb: Refactor CDC VCP code to enable N CDC interfaces. The board config option MICROPY_HW_USB_ENABLE_CDC2 is now changed to MICROPY_HW_USB_CDC_NUM, and the latter should be defined to the maximum number of CDC interfaces to support (defaults to 1). --- ports/stm32/main.c | 4 - ports/stm32/mpconfigboard_common.h | 4 + ports/stm32/usb.c | 79 +++--- ports/stm32/usb.h | 3 +- ports/stm32/usbd_cdc_interface.c | 17 +- ports/stm32/usbd_conf.c | 4 +- .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 14 +- .../usbdev/class/inc/usbd_cdc_msc_hid0.h | 28 +- .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 255 ++++++++---------- 9 files changed, 183 insertions(+), 225 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index ff4589f9d4a08..02449a1b806a3 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -558,10 +558,6 @@ void stm32_main(uint32_t reset_mode) { #if MICROPY_HW_ENABLE_USB pyb_usb_init0(); - - // Activate USB_VCP(0) on dupterm slot 1 for the REPL - MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj); - usb_vcp_attach_to_repl(&pyb_usb_vcp_obj, true); #endif // Initialise the local flash filesystem. diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index b9fa3833ecafd..036e1f6ccdce7 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -264,6 +264,10 @@ #define MICROPY_HW_MAX_CAN (1) #endif +// Configure maximum number of CDC VCP interfaces +#ifndef MICROPY_HW_USB_CDC_NUM +#define MICROPY_HW_USB_CDC_NUM (1) +#endif // Pin definition header file #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h" diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8b7608a150231..c9c22d5d2bbca 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -55,6 +55,8 @@ #endif #endif +STATIC void pyb_usb_vcp_init0(void); + // this will be persistent across a soft-reset mp_uint_t pyb_usb_flags = 0; @@ -62,10 +64,7 @@ typedef struct _usb_device_t { uint32_t enabled; USBD_HandleTypeDef hUSBDDevice; usbd_cdc_msc_hid_state_t usbd_cdc_msc_hid_state; - usbd_cdc_itf_t usbd_cdc_itf; - #if MICROPY_HW_USB_ENABLE_CDC2 - usbd_cdc_itf_t usbd_cdc2_itf; - #endif + usbd_cdc_itf_t usbd_cdc_itf[MICROPY_HW_USB_CDC_NUM]; usbd_hid_itf_t usbd_hid_itf; } usb_device_t; @@ -111,16 +110,15 @@ const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = { }; void pyb_usb_init0(void) { - usb_device.usbd_cdc_itf.attached_to_repl = false; - #if MICROPY_HW_USB_ENABLE_CDC2 - usb_device.usbd_cdc2_itf.attached_to_repl = false; - #endif + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + usb_device.usbd_cdc_itf[i].attached_to_repl = false; + } MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL; + + pyb_usb_vcp_init0(); } -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { - bool high_speed = (mode & USBD_MODE_HIGH_SPEED) != 0; - mode &= 0x7f; +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { usb_device_t *usb_dev = &usb_device; if (!usb_dev->enabled) { // only init USB once in the device's power-lifetime @@ -132,15 +130,15 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors; usbd->pClass = &USBD_CDC_MSC_HID; usb_dev->usbd_cdc_msc_hid_state.pdev = usbd; - usb_dev->usbd_cdc_msc_hid_state.cdc = &usb_dev->usbd_cdc_itf.base; - #if MICROPY_HW_USB_ENABLE_CDC2 - usb_dev->usbd_cdc_msc_hid_state.cdc2 = &usb_dev->usbd_cdc2_itf.base; - #endif + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + usb_dev->usbd_cdc_msc_hid_state.cdc[i] = &usb_dev->usbd_cdc_itf[i].base; + } usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf.base; usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state; // configure the VID, PID and the USBD mode (interfaces it will expose) - USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, mode == USBD_MODE_CDC); + int cdc_only = (mode & USBD_MODE_IFACE_MASK) == USBD_MODE_CDC; + USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, cdc_only); if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info) != 0) { return false; } @@ -157,7 +155,7 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H } // start the USB device - USBD_LL_Init(usbd, high_speed); + USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0); USBD_LL_Start(usbd); usb_dev->enabled = true; } @@ -179,22 +177,17 @@ bool usb_vcp_is_enabled(void) { } int usb_vcp_recv_byte(uint8_t *c) { - return usbd_cdc_rx(&usb_device.usbd_cdc_itf, c, 1, 0); + return usbd_cdc_rx(&usb_device.usbd_cdc_itf[0], c, 1, 0); } void usb_vcp_send_strn(const char *str, int len) { if (usb_device.enabled) { - usbd_cdc_tx_always(&usb_device.usbd_cdc_itf, (const uint8_t*)str, len); + usbd_cdc_tx_always(&usb_device.usbd_cdc_itf[0], (const uint8_t*)str, len); } } usbd_cdc_itf_t *usb_vcp_get(int idx) { - #if MICROPY_HW_USB_ENABLE_CDC2 - if (idx == 1) { - return &usb_device.usbd_cdc2_itf; - } - #endif - return &usb_device.usbd_cdc_itf; + return &usb_device.usbd_cdc_itf[idx]; } /******************************************************************************/ @@ -243,7 +236,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * return MP_OBJ_NEW_QSTR(MP_QSTR_host); #else uint8_t mode = USBD_GetMode(&usb_device.usbd_cdc_msc_hid_state); - switch (mode) { + switch (mode & USBD_MODE_IFACE_MASK) { case USBD_MODE_CDC: return MP_OBJ_NEW_QSTR(MP_QSTR_VCP); case USBD_MODE_MSC: @@ -298,13 +291,13 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // note: we support CDC as a synonym for VCP for backward compatibility uint16_t vid = args[1].u_int; uint16_t pid = args[2].u_int; - usb_device_mode_t mode; + uint8_t mode; if (strcmp(mode_str, "CDC+MSC") == 0 || strcmp(mode_str, "VCP+MSC") == 0) { if (args[2].u_int == -1) { pid = USBD_PID_CDC_MSC; } mode = USBD_MODE_CDC_MSC; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM >= 2 } else if (strcmp(mode_str, "VCP+VCP") == 0) { if (args[2].u_int == -1) { pid = USBD_PID_CDC2; @@ -337,7 +330,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // get hid info if user selected such a mode USBD_HID_ModeInfoTypeDef hid_info; - if (mode & USBD_MODE_HID) { + if (mode & USBD_MODE_IFACE_HID) { mp_obj_t *items; mp_obj_get_array_fixed_n(args[3].u_obj, 5, &items); hid_info.subclass = mp_obj_get_int(items[0]); @@ -388,13 +381,21 @@ typedef struct _pyb_usb_vcp_obj_t { usbd_cdc_itf_t *cdc_itf; } pyb_usb_vcp_obj_t; -const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf}; -#if MICROPY_HW_USB_ENABLE_CDC2 -STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp2_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc2_itf}; -#endif +const pyb_usb_vcp_obj_t pyb_usb_vcp_obj[MICROPY_HW_USB_CDC_NUM] = { + {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[0]}, + #if MICROPY_HW_USB_CDC_NUM >= 2 + {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[1]}, + #endif +}; + +STATIC void pyb_usb_vcp_init0(void) { + // Activate USB_VCP(0) on dupterm slot 1 for the REPL + MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0]); + usb_vcp_attach_to_repl(&pyb_usb_vcp_obj[0], true); +} STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf; + int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf[0]; mp_printf(print, "USB_VCP(%u)", id); } @@ -411,12 +412,8 @@ STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, s // TODO raise exception if USB is not configured for VCP int id = (n_args == 0) ? 0 : mp_obj_get_int(args[0]); - if (id == 0) { - return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj); - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if (id == 1) { - return MP_OBJ_FROM_PTR(&pyb_usb_vcp2_obj); - #endif + if (0 <= id && id < MICROPY_HW_USB_CDC_NUM) { + return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[id]); } else { mp_raise_ValueError(NULL); } @@ -457,7 +454,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_isconnected_obj, pyb_usb_vcp_isconn // deprecated in favour of USB_VCP.isconnected STATIC mp_obj_t pyb_have_cdc(void) { - return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj)); + return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0])); } MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc); diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 3d57bf9129cda..6678e1e17372f 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -58,14 +58,13 @@ extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_mouse_obj; extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj; extern const mp_obj_type_t pyb_usb_vcp_type; extern const mp_obj_type_t pyb_usb_hid_type; -extern const pyb_usb_vcp_obj_t pyb_usb_vcp_obj; MP_DECLARE_CONST_FUN_OBJ_KW(pyb_usb_mode_obj); MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated void pyb_usb_init0(void); -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info); +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info); void pyb_usb_dev_deinit(void); bool usb_vcp_is_enabled(void); int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0 diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index 4a4a8beb8500e..49f0deec71242 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -217,18 +217,13 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { } else { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; - usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc; - if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { - cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED; - usbd_cdc_try_tx(cdc); - } - #if MICROPY_HW_USB_ENABLE_CDC2 - cdc = (usbd_cdc_itf_t*)usbd->cdc2; - if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { - cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED; - usbd_cdc_try_tx(cdc); + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc[i]; + if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { + cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED; + usbd_cdc_try_tx(cdc); + } } - #endif } } diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index b7c1665f0a214..c2e86ccb5b21d 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -334,7 +334,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { if (pdev->id == USB_PHY_FS_ID) { // Set LL Driver parameters pcd_fs_handle.Instance = USB_OTG_FS; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM == 2 pcd_fs_handle.Init.dev_endpoints = 6; #else pcd_fs_handle.Init.dev_endpoints = 4; @@ -364,7 +364,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { HAL_PCD_Init(&pcd_fs_handle); // We have 320 32-bit words in total to use here - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM == 2 HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128); HAL_PCD_SetTxFiFo(&pcd_fs_handle, 0, 32); // EP0 HAL_PCD_SetTxFiFo(&pcd_fs_handle, 1, 64); // MSC / HID diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index 1857273e0725e..f20485a7c0c4f 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -18,12 +18,13 @@ #define USBD_SUPPORT_HS_MODE (0) #endif -// Needed for the CDC+MSC+HID state and should be maximum of all template -// config descriptors defined in usbd_cdc_msc_hid.c -#if MICROPY_HW_USB_ENABLE_CDC2 +// Should be maximum of possible config descriptors that might be configured +#if MICROPY_HW_USB_CDC_NUM == 2 +// Maximum is MSC+CDC+CDC #define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58)) #else -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (107) +// Maximum is HID+CDC +#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 32 + (8 + 58)) #endif // CDC, MSC and HID packet sizes @@ -124,10 +125,7 @@ typedef struct _usbd_cdc_msc_hid_state_t { __ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; __ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END; - usbd_cdc_state_t *cdc; - #if MICROPY_HW_USB_ENABLE_CDC2 - usbd_cdc_state_t *cdc2; - #endif + usbd_cdc_state_t *cdc[MICROPY_HW_USB_CDC_NUM]; usbd_hid_state_t *hid; } usbd_cdc_msc_hid_state_t; diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h index c876dcf2987b2..1cb879180d102 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h @@ -29,18 +29,22 @@ // these are exports for the CDC/MSC/HID interface that are independent // from any other definitions/declarations -// only CDC_MSC and CDC_HID are available -typedef enum { - USBD_MODE_CDC = 0x01, - USBD_MODE_MSC = 0x02, - USBD_MODE_HID = 0x04, - USBD_MODE_CDC2 = 0x08, - USBD_MODE_CDC_MSC = USBD_MODE_CDC | USBD_MODE_MSC, - USBD_MODE_CDC_HID = USBD_MODE_CDC | USBD_MODE_HID, - USBD_MODE_MSC_HID = USBD_MODE_MSC | USBD_MODE_HID, - USBD_MODE_CDC2_MSC = USBD_MODE_CDC | USBD_MODE_MSC | USBD_MODE_CDC2, - USBD_MODE_HIGH_SPEED = 0x80, // or with one of the above -} usb_device_mode_t; +// These can be or'd together (but not all combinations may be available) +#define USBD_MODE_IFACE_MASK (0x7f) +#define USBD_MODE_IFACE_CDC(i) (0x01 << (i)) +#define USBD_MODE_IFACE_HID (0x10) +#define USBD_MODE_IFACE_MSC (0x20) +#define USBD_MODE_HIGH_SPEED (0x80) + +// Convenience macros for supported mode combinations +#define USBD_MODE_CDC (USBD_MODE_IFACE_CDC(0)) +#define USBD_MODE_CDC2 (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1)) +#define USBD_MODE_CDC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_HID) +#define USBD_MODE_CDC_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC) +#define USBD_MODE_CDC2_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC) +#define USBD_MODE_HID (USBD_MODE_IFACE_HID) +#define USBD_MODE_MSC (USBD_MODE_IFACE_MSC) +#define USBD_MODE_MSC_HID (USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) typedef struct _USBD_HID_ModeInfoTypeDef { uint8_t subclass; // 0=no sub class, 1=boot diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 47436a4b63497..bfb5d3058a2d4 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -38,6 +38,8 @@ #define MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC_MSC_TEMPLATE_CDC_DESC_OFFSET (40) +#define CDC2_TEMPLATE_CDC_DESC_OFFSET (9 + 8) +#define CDC2_TEMPLATE_CDC2_DESC_OFFSET (9 + (8 + 58) + 8) #define CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8) #define CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8) @@ -69,13 +71,9 @@ #define HID_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_MSC (1) -#define CDC_IN_EP (0x83) -#define CDC_OUT_EP (0x03) -#define CDC_CMD_EP (0x82) - -#define CDC2_IN_EP (0x85) -#define CDC2_OUT_EP (0x05) -#define CDC2_CMD_EP (0x84) +#define CDC_IN_EP(i) (0x83 + 2 * (i)) +#define CDC_OUT_EP(i) (0x03 + 2 * (i)) +#define CDC_CMD_EP(i) (0x82 + 2 * (i)) #define HID_IN_EP_WITH_CDC (0x81) #define HID_OUT_EP_WITH_CDC (0x01) @@ -232,7 +230,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { // Endpoint CMD Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_CMD_EP, // bEndpointAddress + CDC_CMD_EP(0), // bEndpointAddress 0x03, // bmAttributes: Interrupt LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize: HIBYTE(CDC_CMD_PACKET_SIZE), @@ -253,7 +251,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { // Endpoint OUT Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_OUT_EP, // bEndpointAddress + CDC_OUT_EP(0), // bEndpointAddress 0x02, // bmAttributes: Bulk LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), @@ -262,7 +260,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { // Endpoint IN Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_IN_EP, // bEndpointAddress + CDC_IN_EP(0), // bEndpointAddress 0x02, // bmAttributes: Bulk LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), @@ -421,7 +419,7 @@ static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) { return need_iad ? 8 + 58 : 58; } -#if MICROPY_HW_USB_ENABLE_CDC2 +#if MICROPY_HW_USB_CDC_NUM >= 2 static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, uint8_t cmd_ep, uint8_t out_ep, uint8_t in_ep) { size_t n = make_cdc_desc(dest, need_iad, iface_num); if (need_iad) { @@ -461,7 +459,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode size_t n = HEAD_DESC_SIZE; uint8_t *d = usbd->usbd_config_desc; uint8_t num_itf = 0; - switch (usbd->usbd_mode) { + switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { case USBD_MODE_MSC: n += make_msc_desc(d + n); num_itf = 1; @@ -470,19 +468,16 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode case USBD_MODE_CDC_MSC: n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); - usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; num_itf = 3; break; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM >= 2 case USBD_MODE_CDC2: { - // Ensure the first interface is also enabled - usbd->usbd_mode |= USBD_MODE_CDC; - n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE); - n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP); - usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE; - usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_CDC; + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_CDC; num_itf = 4; break; } @@ -490,9 +485,9 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode case USBD_MODE_CDC2_MSC: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); - n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP); - usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC; - usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_MSC; + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; num_itf = 5; break; } @@ -502,7 +497,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode usbd->hid->desc = d + n; n += make_hid_desc(d + n, hid_info); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID); - usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_HID; + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_HID; usbd->hid->in_ep = HID_IN_EP_WITH_CDC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC; @@ -512,7 +507,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode case USBD_MODE_CDC: n += make_cdc_desc(d + n, 0, CDC_IFACE_NUM_ALONE); - usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE; + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; num_itf = 2; break; @@ -533,17 +528,12 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode make_head_desc(d, n, num_itf); usbd->usbd_config_desc_size = n; - if (usbd->usbd_mode & USBD_MODE_CDC) { - usbd->cdc->in_ep = CDC_IN_EP; - usbd->cdc->out_ep = CDC_OUT_EP; - } - - #if MICROPY_HW_USB_ENABLE_CDC2 - if (usbd->usbd_mode & USBD_MODE_CDC2) { - usbd->cdc2->in_ep = CDC2_IN_EP; - usbd->cdc2->out_ep = CDC2_OUT_EP; + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) { + usbd->cdc[i]->in_ep = CDC_IN_EP(i); + usbd->cdc[i]->out_ep = CDC_OUT_EP(i); + } } - #endif return 0; } @@ -578,19 +568,14 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if (usbd->usbd_mode & USBD_MODE_CDC) { - // CDC VCP component - usbd_cdc_state_init(pdev, usbd, usbd->cdc, CDC_CMD_EP); - } - - #if MICROPY_HW_USB_ENABLE_CDC2 - if (usbd->usbd_mode & USBD_MODE_CDC2) { - // CDC VCP #2 component - usbd_cdc_state_init(pdev, usbd, usbd->cdc2, CDC2_CMD_EP); + // CDC VCP component(s) + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) { + usbd_cdc_state_init(pdev, usbd, usbd->cdc[i], CDC_CMD_EP(i)); + } } - #endif - if (usbd->usbd_mode & USBD_MODE_MSC) { + if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component int mp = usbd_msc_max_packet(pdev); @@ -611,7 +596,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { MSC_BOT_Init(pdev); } - if (usbd->usbd_mode & USBD_MODE_HID) { + if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component // get max packet lengths from descriptor @@ -644,31 +629,20 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if ((usbd->usbd_mode & USBD_MODE_CDC) && usbd->cdc) { - // CDC VCP component - - usbd_cdc_deinit(usbd->cdc); - - // close endpoints - USBD_LL_CloseEP(pdev, CDC_IN_EP); - USBD_LL_CloseEP(pdev, CDC_OUT_EP); - USBD_LL_CloseEP(pdev, CDC_CMD_EP); - } - - #if MICROPY_HW_USB_ENABLE_CDC2 - if ((usbd->usbd_mode & USBD_MODE_CDC2) && usbd->cdc2) { - // CDC VCP #2 component + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && usbd->cdc[i]) { + // CDC VCP component - usbd_cdc_deinit(usbd->cdc2); + usbd_cdc_deinit(usbd->cdc[i]); - // close endpoints - USBD_LL_CloseEP(pdev, CDC2_IN_EP); - USBD_LL_CloseEP(pdev, CDC2_OUT_EP); - USBD_LL_CloseEP(pdev, CDC2_CMD_EP); + // close endpoints + USBD_LL_CloseEP(pdev, CDC_IN_EP(i)); + USBD_LL_CloseEP(pdev, CDC_OUT_EP(i)); + USBD_LL_CloseEP(pdev, CDC_CMD_EP(i)); + } } - #endif - if (usbd->usbd_mode & USBD_MODE_MSC) { + if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component // close endpoints @@ -679,7 +653,7 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) MSC_BOT_DeInit(pdev); } - if (usbd->usbd_mode & USBD_MODE_HID) { + if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component // close endpoints @@ -717,35 +691,35 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) { case USB_REQ_RECIPIENT_INTERFACE: { uint16_t iface = req->wIndex; - if ((mode & USBD_MODE_CDC) && iface == usbd->cdc->iface_num) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc; - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((mode & USBD_MODE_CDC2) && iface == usbd->cdc2->iface_num) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc2; - #endif - } else if ((mode & USBD_MODE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { + if ((mode & USBD_MODE_IFACE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { recipient = USBD_MODE_MSC; - } else if ((mode & USBD_MODE_HID) && iface == usbd->hid->iface_num) { + } else if ((mode & USBD_MODE_IFACE_HID) && iface == usbd->hid->iface_num) { recipient = USBD_MODE_HID; + } else { + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((mode & USBD_MODE_IFACE_CDC(i)) && iface == usbd->cdc[i]->iface_num) { + recipient = USBD_MODE_CDC; + cdc = usbd->cdc[i]; + break; + } + } } break; } case USB_REQ_RECIPIENT_ENDPOINT: { uint8_t ep = req->wIndex & 0x7f; - if ((mode & USBD_MODE_CDC) && (ep == CDC_OUT_EP || ep == (CDC_CMD_EP & 0x7f))) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc; - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((mode & USBD_MODE_CDC2) && (ep == CDC2_OUT_EP || ep == (CDC2_CMD_EP & 0x7f))) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc2; - #endif - } else if ((mode & USBD_MODE_MSC) && ep == MSC_OUT_EP) { + if ((mode & USBD_MODE_IFACE_MSC) && ep == MSC_OUT_EP) { recipient = USBD_MODE_MSC; - } else if ((mode & USBD_MODE_HID) && ep == usbd->hid->out_ep) { + } else if ((mode & USBD_MODE_IFACE_HID) && ep == usbd->hid->out_ep) { recipient = USBD_MODE_HID; + } else { + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((mode & USBD_MODE_IFACE_CDC(i)) && (ep == CDC_OUT_EP(i) || ep == (CDC_CMD_EP(i) & 0x7f))) { + recipient = USBD_MODE_CDC; + cdc = usbd->cdc[i]; + break; + } + } } break; } @@ -894,36 +868,32 @@ static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) { static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if (usbd->cdc != NULL && usbd->cdc->cur_request != 0xff) { - usbd_cdc_control(usbd->cdc, usbd->cdc->cur_request, (uint8_t*)usbd->cdc->ctl_packet_buf, usbd->cdc->cur_length); - usbd->cdc->cur_request = 0xff; - } - #if MICROPY_HW_USB_ENABLE_CDC2 - if (usbd->cdc2 != NULL && usbd->cdc2->cur_request != 0xff) { - usbd_cdc_control(usbd->cdc2, usbd->cdc2->cur_request, (uint8_t*)usbd->cdc2->ctl_packet_buf, usbd->cdc2->cur_length); - usbd->cdc2->cur_request = 0xff; + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (usbd->cdc[i] != NULL && usbd->cdc[i]->cur_request != 0xff) { + usbd_cdc_control(usbd->cdc[i], usbd->cdc[i]->cur_request, (uint8_t*)usbd->cdc[i]->ctl_packet_buf, usbd->cdc[i]->cur_length); + usbd->cdc[i]->cur_request = 0xff; + } } - #endif - return USBD_OK; } static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if ((usbd->usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) { - usbd->cdc->tx_in_progress = 0; - usbd_cdc_tx_ready(usbd->cdc); - return USBD_OK; - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((usbd->usbd_mode & USBD_MODE_CDC2) && (epnum == (CDC2_IN_EP & 0x7f) || epnum == (CDC2_CMD_EP & 0x7f))) { - usbd->cdc2->tx_in_progress = 0; - usbd_cdc_tx_ready(usbd->cdc2); - return USBD_OK; - #endif - } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { + + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && (epnum == (CDC_IN_EP(i) & 0x7f) || epnum == (CDC_CMD_EP(i) & 0x7f))) { + usbd->cdc[i]->tx_in_progress = 0; + usbd_cdc_tx_ready(usbd->cdc[i]); + return USBD_OK; + } + } + + if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { MSC_BOT_DataIn(pdev, epnum); return USBD_OK; - } else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { + } + + if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { /* Ensure that the FIFO is empty before a new transfer, this condition could be caused by a new transfer before the end of the previous transfer */ usbd->hid->state = HID_IDLE; @@ -935,26 +905,23 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if ((usbd->usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) { - /* Get the received data length */ - size_t len = USBD_LL_GetRxDataSize (pdev, epnum); - /* USB data will be immediately processed, this allow next USB traffic being - NAKed till the end of the application Xfer */ - return usbd_cdc_receive(usbd->cdc, len); + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && epnum == (CDC_OUT_EP(i) & 0x7f)) { + size_t len = USBD_LL_GetRxDataSize(pdev, epnum); + // USB data will be immediately processed, and next USB traffic is NAKed until it's done + return usbd_cdc_receive(usbd->cdc[i], len); + } + } - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((usbd->usbd_mode & USBD_MODE_CDC2) && epnum == (CDC2_OUT_EP & 0x7f)) { - size_t len = USBD_LL_GetRxDataSize(pdev, epnum); - return usbd_cdc_receive(usbd->cdc2, len); - - #endif - } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { MSC_BOT_DataOut(pdev, epnum); return USBD_OK; - } else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) { + } + + if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) { size_t len = USBD_LL_GetRxDataSize(pdev, epnum); - usbd_hid_receive(usbd->hid, len); + return usbd_hid_receive(usbd->hid, len); } return USBD_OK; @@ -981,48 +948,46 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; #if USBD_SUPPORT_HS_MODE - uint8_t *cdc_desc = NULL; - #if MICROPY_HW_USB_ENABLE_CDC2 - uint8_t *cdc2_desc = NULL; - #endif + uint8_t *cdc_desc[MICROPY_HW_USB_CDC_NUM] = {0}; uint8_t *msc_desc = NULL; - switch (usbd->usbd_mode) { + switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { case USBD_MODE_MSC: msc_desc = usbd->usbd_config_desc + MSC_TEMPLATE_MSC_DESC_OFFSET; break; case USBD_MODE_CDC_MSC: - cdc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_MSC_DESC_OFFSET; break; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM >= 2 + case USBD_MODE_CDC2: + cdc_desc[0] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[1] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC2_DESC_OFFSET; + break; + case USBD_MODE_CDC2_MSC: - cdc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET; - cdc2_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[1] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET; break; #endif case USBD_MODE_CDC_HID: - cdc_desc = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET; break; case USBD_MODE_CDC: - cdc_desc = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET; break; } // configure CDC descriptors, if needed - if (cdc_desc != NULL) { - usbd_cdc_desc_config_max_packet(pdev, cdc_desc); - } - - #if MICROPY_HW_USB_ENABLE_CDC2 - if (cdc2_desc != NULL) { - usbd_cdc_desc_config_max_packet(pdev, cdc2_desc); + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (cdc_desc[i] != NULL) { + usbd_cdc_desc_config_max_packet(pdev, cdc_desc[i]); + } } - #endif if (msc_desc != NULL) { uint32_t mp = usbd_msc_max_packet(pdev); From ff91b05cfa8154d1a4d098423dfa95d14ade4271 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 May 2019 17:16:15 +1000 Subject: [PATCH 0130/1299] stm32/usb: Support up to 3 VCP interfaces on USB device peripheral. To enable define MICROPY_HW_USB_CDC_NUM to 3. --- ports/stm32/usb.c | 15 ++++++ ports/stm32/usb.h | 2 + ports/stm32/usbd_conf.c | 12 +++++ ports/stm32/usbd_conf.h | 2 +- .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 5 +- .../usbdev/class/inc/usbd_cdc_msc_hid0.h | 2 + .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 49 +++++++++++++++++++ 7 files changed, 85 insertions(+), 2 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index c9c22d5d2bbca..ace090f804bb0 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -309,6 +309,18 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * } mode = USBD_MODE_CDC2_MSC; #endif + #if MICROPY_HW_USB_CDC_NUM >= 3 + } else if (strcmp(mode_str, "3xVCP") == 0) { + if (args[2].u_int == -1) { + pid = USBD_PID_CDC3; + } + mode = USBD_MODE_CDC3; + } else if (strcmp(mode_str, "3xVCP+MSC") == 0) { + if (args[2].u_int == -1) { + pid = USBD_PID_CDC3_MSC; + } + mode = USBD_MODE_CDC3_MSC; + #endif } else if (strcmp(mode_str, "CDC+HID") == 0 || strcmp(mode_str, "VCP+HID") == 0) { if (args[2].u_int == -1) { pid = USBD_PID_CDC_HID; @@ -386,6 +398,9 @@ const pyb_usb_vcp_obj_t pyb_usb_vcp_obj[MICROPY_HW_USB_CDC_NUM] = { #if MICROPY_HW_USB_CDC_NUM >= 2 {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[1]}, #endif + #if MICROPY_HW_USB_CDC_NUM >= 3 + {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[2]}, + #endif }; STATIC void pyb_usb_vcp_init0(void) { diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 6678e1e17372f..0aa50f9e77772 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -38,6 +38,8 @@ #define USBD_PID_MSC (0x9803) #define USBD_PID_CDC2_MSC (0x9804) #define USBD_PID_CDC2 (0x9805) +#define USBD_PID_CDC3 (0x9806) +#define USBD_PID_CDC3_MSC (0x9807) typedef enum { PYB_USB_STORAGE_MEDIUM_NONE = 0, diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index c2e86ccb5b21d..ed99700e9994f 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -385,7 +385,11 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { if (pdev->id == USB_PHY_HS_ID) { // Set LL Driver parameters pcd_hs_handle.Instance = USB_OTG_HS; + #if MICROPY_HW_USB_CDC_NUM == 3 + pcd_hs_handle.Init.dev_endpoints = 8; + #else pcd_hs_handle.Init.dev_endpoints = 6; + #endif pcd_hs_handle.Init.use_dedicated_ep1 = 0; pcd_hs_handle.Init.ep0_mps = 0x40; pcd_hs_handle.Init.dma_enable = 0; @@ -431,13 +435,21 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { HAL_PCD_Init(&pcd_hs_handle); // We have 1024 32-bit words in total to use here + #if MICROPY_HW_USB_CDC_NUM == 3 + HAL_PCD_SetRxFiFo(&pcd_hs_handle, 328); + #else HAL_PCD_SetRxFiFo(&pcd_hs_handle, 464); + #endif HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 32); // EP0 HAL_PCD_SetTxFiFo(&pcd_hs_handle, 1, 256); // MSC / HID HAL_PCD_SetTxFiFo(&pcd_hs_handle, 2, 8); // CDC CMD HAL_PCD_SetTxFiFo(&pcd_hs_handle, 3, 128); // CDC DATA HAL_PCD_SetTxFiFo(&pcd_hs_handle, 4, 8); // CDC2 CMD HAL_PCD_SetTxFiFo(&pcd_hs_handle, 5, 128); // CDC2 DATA + #if MICROPY_HW_USB_CDC_NUM == 3 + HAL_PCD_SetTxFiFo(&pcd_hs_handle, 6, 8); // CDC3 CMD + HAL_PCD_SetTxFiFo(&pcd_hs_handle, 7, 128); // CDC3 DATA + #endif } #endif // MICROPY_HW_USB_HS diff --git a/ports/stm32/usbd_conf.h b/ports/stm32/usbd_conf.h index c5faf6c8c8879..639b54d9f39c0 100644 --- a/ports/stm32/usbd_conf.h +++ b/ports/stm32/usbd_conf.h @@ -39,7 +39,7 @@ #include "py/mpconfig.h" -#define USBD_MAX_NUM_INTERFACES 4 +#define USBD_MAX_NUM_INTERFACES 5 #define USBD_MAX_NUM_CONFIGURATION 1 #define USBD_MAX_STR_DESC_SIZ 0x100 #if MICROPY_HW_USB_SELF_POWERED diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index f20485a7c0c4f..d4a218a4a6f4b 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -19,7 +19,10 @@ #endif // Should be maximum of possible config descriptors that might be configured -#if MICROPY_HW_USB_CDC_NUM == 2 +#if MICROPY_HW_USB_CDC_NUM == 3 +// Maximum is MSC+CDC+CDC+CDC +#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58) + (8 + 58)) +#elif MICROPY_HW_USB_CDC_NUM == 2 // Maximum is MSC+CDC+CDC #define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58)) #else diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h index 1cb879180d102..63fe8ecefc77f 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h @@ -39,9 +39,11 @@ // Convenience macros for supported mode combinations #define USBD_MODE_CDC (USBD_MODE_IFACE_CDC(0)) #define USBD_MODE_CDC2 (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1)) +#define USBD_MODE_CDC3 (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2)) #define USBD_MODE_CDC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_HID) #define USBD_MODE_CDC_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC) #define USBD_MODE_CDC2_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC) +#define USBD_MODE_CDC3_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2) | USBD_MODE_IFACE_MSC) #define USBD_MODE_HID (USBD_MODE_IFACE_HID) #define USBD_MODE_MSC (USBD_MODE_IFACE_MSC) #define USBD_MODE_MSC_HID (USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index bfb5d3058a2d4..d982fe8e6f6b5 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -43,6 +43,13 @@ #define CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8) #define CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8) +#define CDC3_TEMPLATE_CDC_DESC_OFFSET (9 + 8) +#define CDC3_TEMPLATE_CDC2_DESC_OFFSET (9 + (8 + 58) + 8) +#define CDC3_TEMPLATE_CDC3_DESC_OFFSET (9 + (8 + 58) + (8 + 58) + 8) +#define CDC3_MSC_TEMPLATE_MSC_DESC_OFFSET (9) +#define CDC3_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8) +#define CDC3_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8) +#define CDC3_MSC_TEMPLATE_CDC3_DESC_OFFSET (9 + 23 + (8 + 58) + (8 + 58) + 8) #define CDC_HID_TEMPLATE_CDC_DESC_OFFSET (49) #define CDC_TEMPLATE_CDC_DESC_OFFSET (9) #define CDC_DESC_OFFSET_INTR_INTERVAL (34) @@ -65,7 +72,9 @@ #define CDC_IFACE_NUM_ALONE (0) #define CDC_IFACE_NUM_WITH_MSC (1) #define CDC2_IFACE_NUM_WITH_CDC (2) +#define CDC3_IFACE_NUM_WITH_CDC (4) #define CDC2_IFACE_NUM_WITH_MSC (3) +#define CDC3_IFACE_NUM_WITH_MSC (5) #define CDC_IFACE_NUM_WITH_HID (1) #define MSC_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_CDC (0) @@ -493,6 +502,31 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode } #endif + #if MICROPY_HW_USB_CDC_NUM >= 3 + case USBD_MODE_CDC3: { + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE); + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + n += make_cdc_desc_ep(d + n, 1, CDC3_IFACE_NUM_WITH_CDC, CDC_CMD_EP(2), CDC_OUT_EP(2), CDC_IN_EP(2)); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_CDC; + usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_CDC; + num_itf = 6; + break; + } + + case USBD_MODE_CDC3_MSC: { + n += make_msc_desc(d + n); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + n += make_cdc_desc_ep(d + n, 1, CDC3_IFACE_NUM_WITH_MSC, CDC_CMD_EP(2), CDC_OUT_EP(2), CDC_IN_EP(2)); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; + usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; + num_itf = 7; + break; + } + #endif + case USBD_MODE_CDC_HID: usbd->hid->desc = d + n; n += make_hid_desc(d + n, hid_info); @@ -973,6 +1007,21 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * break; #endif + #if MICROPY_HW_USB_CDC_NUM >= 3 + case USBD_MODE_CDC3: + cdc_desc[0] = usbd->usbd_config_desc + CDC3_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[1] = usbd->usbd_config_desc + CDC3_TEMPLATE_CDC2_DESC_OFFSET; + cdc_desc[2] = usbd->usbd_config_desc + CDC3_TEMPLATE_CDC3_DESC_OFFSET; + break; + + case USBD_MODE_CDC3_MSC: + cdc_desc[0] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[1] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC2_DESC_OFFSET; + cdc_desc[2] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC3_DESC_OFFSET; + msc_desc = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_MSC_DESC_OFFSET; + break; + #endif + case USBD_MODE_CDC_HID: cdc_desc[0] = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET; break; From de76f73d34a63fa34c520125f226e0c159ce0b10 Mon Sep 17 00:00:00 2001 From: Martin Dybdal Date: Fri, 24 May 2019 13:19:26 +0200 Subject: [PATCH 0131/1299] esp32/machine_timer: Reuse Timer handles, deallocate only on soft-reset. The patch solves the problem where multiple Timer objects (e.g. multiple Timer(0) instances) could initialise multiple handles to the same internal timer. The list of timers is now maintained not for "active" timers (where init is called), but for all timers created. The timers are only removed from the list of timers on soft-reset (machine_timer_deinit_all). Fixes #4078. --- ports/esp32/machine_timer.c | 40 ++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c index 081a46b9c1c50..c941d943bcb40 100644 --- a/ports/esp32/machine_timer.c +++ b/ports/esp32/machine_timer.c @@ -73,8 +73,13 @@ STATIC esp_err_t check_esp_err(esp_err_t code) { } void machine_timer_deinit_all(void) { - while (MP_STATE_PORT(machine_timer_obj_head) != NULL) { - machine_timer_disable(MP_STATE_PORT(machine_timer_obj_head)); + // Disable, deallocate and remove all timers from list + machine_timer_obj_t **t = &MP_STATE_PORT(machine_timer_obj_head); + while (*t != NULL) { + machine_timer_disable(*t); + machine_timer_obj_t *next = (*t)->next; + m_del_obj(machine_timer_obj_t, *t); + *t = next; } } @@ -93,12 +98,24 @@ STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_pr STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); + mp_uint_t group = (mp_obj_get_int(args[0]) >> 1) & 1; + mp_uint_t index = mp_obj_get_int(args[0]) & 1; + + // Check whether the timer is already initialized, if so return it + for (machine_timer_obj_t *t = MP_STATE_PORT(machine_timer_obj_head); t; t = t->next) { + if (t->group == group && t->index == index) { + return t; + } + } + machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); self->base.type = &machine_timer_type; + self->group = group; + self->index = index; - self->group = (mp_obj_get_int(args[0]) >> 1) & 1; - self->index = mp_obj_get_int(args[0]) & 1; - self->next = NULL; + // Add the timer to the linked-list of timers + self->next = MP_STATE_PORT(machine_timer_obj_head); + MP_STATE_PORT(machine_timer_obj_head) = self; return self; } @@ -110,13 +127,8 @@ STATIC void machine_timer_disable(machine_timer_obj_t *self) { self->handle = NULL; } - // Remove the timer from the linked-list of active timers - for (machine_timer_obj_t **t = &MP_STATE_PORT(machine_timer_obj_head); *t; t = &(*t)->next) { - if (*t == self) { - *t = (*t)->next; - break; - } - } + // We let the disabled timer stay in the list, as it might be + // referenced elsewhere } STATIC void machine_timer_isr(void *self_in) { @@ -150,10 +162,6 @@ STATIC void machine_timer_enable(machine_timer_obj_t *self) { check_esp_err(timer_enable_intr(self->group, self->index)); check_esp_err(timer_isr_register(self->group, self->index, machine_timer_isr, (void*)self, TIMER_FLAGS, &self->handle)); check_esp_err(timer_start(self->group, self->index)); - - // Add the timer to the linked-list of active timers - self->next = MP_STATE_PORT(machine_timer_obj_head); - MP_STATE_PORT(machine_timer_obj_head) = self; } STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { From 3fc7c8e35c24942f1b44eb99e0aba9cf77ab984c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 May 2019 21:39:34 +1000 Subject: [PATCH 0132/1299] stm32/usb: Include py/mpconfig.h instead of mpconfigboard.h. Because py/mpconfig.h has header include guards. --- ports/stm32/usbd_desc.c | 2 +- ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ports/stm32/usbd_desc.c b/ports/stm32/usbd_desc.c index a7de71ef20394..d28f9aec6fa6e 100644 --- a/ports/stm32/usbd_desc.c +++ b/ports/stm32/usbd_desc.c @@ -37,7 +37,7 @@ #include "py/mphal.h" // need this header for any overrides to the below constants -#include "mpconfigboard.h" +#include "py/mpconfig.h" #ifndef USBD_LANGID_STRING #define USBD_LANGID_STRING 0x409 diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index d4a218a4a6f4b..d46f763d1dc41 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -7,8 +7,7 @@ #include "usbd_ioreq.h" // These are included to get direct access the MICROPY_HW_USB_xxx config -#include "mpconfigboard.h" -#include "mpconfigboard_common.h" +#include "py/mpconfig.h" // Work out if we should support USB high-speed device mode #if MICROPY_HW_USB_HS \ From f8274d5e7d95283f39bd73e521b0edd820765541 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 May 2019 21:41:30 +1000 Subject: [PATCH 0133/1299] stm32/boards/make-pins.py: Allow pins.csv to skip or hide board-pin name If the board-pin name is left empty then only the cpu-pin name is used, eg ",PA0". If the board-pin name starts with a hyphen then it's available as a C definition but not in the firmware, eg "-X1,PA0". --- ports/stm32/boards/make-pins.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/make-pins.py b/ports/stm32/boards/make-pins.py index ed112e05f0f32..3819b47244f7b 100755 --- a/ports/stm32/boards/make-pins.py +++ b/ports/stm32/boards/make-pins.py @@ -251,9 +251,17 @@ def qstr_list(self): class NamedPin(object): def __init__(self, name, pin): - self._name = name + if name.startswith('-'): + self._is_hidden = True + self._name = name[1:] + else: + self._is_hidden = False + self._name = name self._pin = pin + def is_hidden(self): + return self._is_hidden + def pin(self): return self._pin @@ -300,13 +308,14 @@ def parse_board_file(self, filename): pin = self.find_pin(port_num, pin_num) if pin: pin.set_is_board_pin() - self.board_pins.append(NamedPin(row[0], pin)) + if row[0]: # Only add board pins that have a name + self.board_pins.append(NamedPin(row[0], pin)) def print_named(self, label, named_pins): print('STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label)) for named_pin in named_pins: pin = named_pin.pin() - if pin.is_board_pin(): + if pin.is_board_pin() and not named_pin.is_hidden(): print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}_obj) }},'.format(named_pin.name(), pin.cpu_pin_name())) print('};') print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label)) @@ -364,7 +373,8 @@ def print_qstr(self, qstr_filename): qstr_set |= set(pin.qstr_list()) qstr_set |= set([named_pin.name()]) for named_pin in self.board_pins: - qstr_set |= set([named_pin.name()]) + if not named_pin.is_hidden(): + qstr_set |= set([named_pin.name()]) for qstr in sorted(qstr_set): cond_var = None if qstr.startswith('AF'): @@ -429,6 +439,8 @@ def print_af_py(self, af_py_filename): with open(af_py_filename, 'wt') as af_py_file: print('PINS_AF = (', file=af_py_file) for named_pin in self.board_pins: + if named_pin.is_hidden(): + continue print(" ('%s', " % named_pin.name(), end='', file=af_py_file) for af in named_pin.pin().alt_fn: if af.is_supported(): From 34cae24e3030456534abda794cc870051ac0491d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 May 2019 21:44:53 +1000 Subject: [PATCH 0134/1299] stm32/boards/pllvalues.py: Search nested headers for HSx_VALUE defines. --- ports/stm32/boards/pllvalues.py | 43 +++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/ports/stm32/boards/pllvalues.py b/ports/stm32/boards/pllvalues.py index da1b81216fdf4..a628dea8a9c64 100644 --- a/ports/stm32/boards/pllvalues.py +++ b/ports/stm32/boards/pllvalues.py @@ -135,6 +135,27 @@ def print_table(hse, valid_plls): print(out_format % ((sys,) + pll + compute_derived(hse, pll))) print("found %u valid configurations" % len(valid_plls)) +def search_header_for_hsx_values(filename, vals): + regex_inc = re.compile(r'#include "(boards/[A-Za-z0-9_./]+)"') + regex_def = re.compile(r'#define +(HSE_VALUE|HSI_VALUE) +\(\(uint32_t\)([0-9]+)\)') + with open(filename) as f: + for line in f: + line = line.strip() + m = regex_inc.match(line) + if m: + # Search included file + search_header_for_hsx_values(m.group(1), vals) + continue + m = regex_def.match(line) + if m: + # Found HSE_VALUE or HSI_VALUE + val = int(m.group(2)) // 1000000 + if m.group(1) == 'HSE_VALUE': + vals[0] = val + else: + vals[1] = val + return vals + def main(): global out_format @@ -163,22 +184,12 @@ def main(): if argv[0].startswith("file:"): # extract HSE_VALUE, and optionally HSI_VALUE, from header file - regex = re.compile(r'#define +(HSE_VALUE|HSI_VALUE) +\(\(uint32_t\)([0-9]+)\)') - with open(argv[0][5:]) as f: - for line in f: - line = line.strip() - m = regex.match(line) - if m: - val = int(m.group(2)) // 1000000 - if m.group(1) == 'HSE_VALUE': - hse = val - else: - hsi = val - if hse is None: - raise ValueError("%s does not contain a definition of HSE_VALUE" % argv[0]) - if hsi is not None and hsi > 16: - # Currently, a HSI value greater than 16MHz is not supported - hsi = None + hse, hsi = search_header_for_hsx_values(argv[0][5:], [None, None]) + if hse is None: + raise ValueError("%s does not contain a definition of HSE_VALUE" % argv[0]) + if hsi is not None and hsi > 16: + # Currently, a HSI value greater than 16MHz is not supported + hsi = None else: # HSE given directly as an integer hse = int(argv[0]) From 8f55c74533b7106daddbfccb38b85056c8a549f5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 May 2019 22:17:02 +1000 Subject: [PATCH 0135/1299] stm32/boards: Add board definition files for PYBD -SF2, -SF3, -SF6. These are core configurations providing PYBv1.x-level features. --- ports/stm32/boards/PYBD_SF2/bdev.c | 62 ++++++ ports/stm32/boards/PYBD_SF2/board_init.c | 38 ++++ ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 97 +++++++++ ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 201 ++++++++++++++++++ ports/stm32/boards/PYBD_SF2/mpconfigboard.mk | 10 + ports/stm32/boards/PYBD_SF2/pins.csv | 189 ++++++++++++++++ .../boards/PYBD_SF2/stm32f7xx_hal_conf.h | 88 ++++++++ ports/stm32/boards/PYBD_SF3/bdev.c | 1 + ports/stm32/boards/PYBD_SF3/board_init.c | 1 + ports/stm32/boards/PYBD_SF3/mpconfigboard.h | 34 +++ ports/stm32/boards/PYBD_SF3/mpconfigboard.mk | 13 ++ ports/stm32/boards/PYBD_SF3/pins.csv | 189 ++++++++++++++++ .../boards/PYBD_SF3/stm32f7xx_hal_conf.h | 1 + ports/stm32/boards/PYBD_SF6/bdev.c | 1 + ports/stm32/boards/PYBD_SF6/board_init.c | 1 + ports/stm32/boards/PYBD_SF6/f767.ld | 96 +++++++++ ports/stm32/boards/PYBD_SF6/mpconfigboard.h | 66 ++++++ ports/stm32/boards/PYBD_SF6/mpconfigboard.mk | 10 + ports/stm32/boards/PYBD_SF6/pins.csv | 189 ++++++++++++++++ .../boards/PYBD_SF6/stm32f7xx_hal_conf.h | 1 + 20 files changed, 1288 insertions(+) create mode 100644 ports/stm32/boards/PYBD_SF2/bdev.c create mode 100644 ports/stm32/boards/PYBD_SF2/board_init.c create mode 100644 ports/stm32/boards/PYBD_SF2/f722_qspi.ld create mode 100644 ports/stm32/boards/PYBD_SF2/mpconfigboard.h create mode 100644 ports/stm32/boards/PYBD_SF2/mpconfigboard.mk create mode 100644 ports/stm32/boards/PYBD_SF2/pins.csv create mode 100644 ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h create mode 100644 ports/stm32/boards/PYBD_SF3/bdev.c create mode 100644 ports/stm32/boards/PYBD_SF3/board_init.c create mode 100644 ports/stm32/boards/PYBD_SF3/mpconfigboard.h create mode 100644 ports/stm32/boards/PYBD_SF3/mpconfigboard.mk create mode 100644 ports/stm32/boards/PYBD_SF3/pins.csv create mode 100644 ports/stm32/boards/PYBD_SF3/stm32f7xx_hal_conf.h create mode 100644 ports/stm32/boards/PYBD_SF6/bdev.c create mode 100644 ports/stm32/boards/PYBD_SF6/board_init.c create mode 100644 ports/stm32/boards/PYBD_SF6/f767.ld create mode 100644 ports/stm32/boards/PYBD_SF6/mpconfigboard.h create mode 100644 ports/stm32/boards/PYBD_SF6/mpconfigboard.mk create mode 100644 ports/stm32/boards/PYBD_SF6/pins.csv create mode 100644 ports/stm32/boards/PYBD_SF6/stm32f7xx_hal_conf.h diff --git a/ports/stm32/boards/PYBD_SF2/bdev.c b/ports/stm32/boards/PYBD_SF2/bdev.c new file mode 100644 index 0000000000000..6c5ff721ec707 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/bdev.c @@ -0,0 +1,62 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "storage.h" +#include "qspi.h" + +// Shared cache for first and second SPI block devices +STATIC mp_spiflash_cache_t spi_bdev_cache; + +// First external SPI flash uses software QSPI interface + +STATIC const mp_soft_qspi_obj_t soft_qspi_bus = { + .cs = MICROPY_HW_SPIFLASH_CS, + .clk = MICROPY_HW_SPIFLASH_SCK, + .io0 = MICROPY_HW_SPIFLASH_IO0, + .io1 = MICROPY_HW_SPIFLASH_IO1, + .io2 = MICROPY_HW_SPIFLASH_IO2, + .io3 = MICROPY_HW_SPIFLASH_IO3, +}; + +const mp_spiflash_config_t spiflash_config = { + .bus_kind = MP_SPIFLASH_BUS_QSPI, + .bus.u_qspi.data = (void*)&soft_qspi_bus, + .bus.u_qspi.proto = &mp_soft_qspi_proto, + .cache = &spi_bdev_cache, +}; + +spi_bdev_t spi_bdev; + +// Second external SPI flash uses hardware QSPI interface + +const mp_spiflash_config_t spiflash2_config = { + .bus_kind = MP_SPIFLASH_BUS_QSPI, + .bus.u_qspi.data = NULL, + .bus.u_qspi.proto = &qspi_proto, + .cache = &spi_bdev_cache, +}; + +spi_bdev_t spi_bdev2; diff --git a/ports/stm32/boards/PYBD_SF2/board_init.c b/ports/stm32/boards/PYBD_SF2/board_init.c new file mode 100644 index 0000000000000..3dc2c85e22a21 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/board_init.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mphal.h" +#include "storage.h" + +void mboot_board_early_init(void) { + // Enable 500mA on WBUS-DIP28 + mp_hal_pin_config(pyb_pin_W23, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); +} + +void board_early_init(void) { + // Explicitly init SPI2 because it's not enabled as a block device + spi_bdev_ioctl(&spi_bdev2, BDEV_IOCTL_INIT, (uint32_t)&spiflash2_config); +} diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld new file mode 100644 index 0000000000000..8cafb0abe6f5b --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -0,0 +1,97 @@ +/* + Linker script for PYBD with STM32F722/STM32F723/STM32F732/STM32F733 + + Memory layout for mboot configuration (this here describes the app part): + + FLASH_APP .isr_vector + FLASH_APP .text + FLASH_APP .data + + RAM .data + RAM .bss + RAM .heap + RAM .stack +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K + FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sectors 0,1 */ + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 480K /* sectors 2-7 */ + FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 256K /* DTCM+SRAM1+SRAM2 */ +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* Define tho top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _ram_end - 16K; /* 16k stack */ + +ENTRY(Reset_Handler) + +/* Define output sections */ +SECTIONS +{ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } >FLASH_APP + + .text : + { + . = ALIGN(4); + *(.text*) + *(.rodata*) + . = ALIGN(4); + _etext = .; + } >FLASH_APP + + _sidata = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data*) + + . = ALIGN(4); + _edata = .; + } >RAM AT> FLASH_APP + + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >RAM + + .heap : + { + . = ALIGN(4); + . = . + _minimum_heap_size; + . = ALIGN(4); + } >RAM + + .stack : + { + . = ALIGN(4); + . = . + _minimum_stack_size; + . = ALIGN(4); + } >RAM +} diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h new file mode 100644 index 0000000000000..56650ba1580c1 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -0,0 +1,201 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define MICROPY_HW_BOARD_NAME "PYBD-SF2W" +#define MICROPY_HW_MCU_NAME "STM32F722IEK" + +#define MICROPY_PY_PYB_LEGACY (1) +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_TIMER (1) +#define MICROPY_HW_ENABLE_SERVO (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_ENABLE_SDCARD (1) +#define MICROPY_HW_ENABLE_MMCARD (1) + +#define MICROPY_BOARD_EARLY_INIT board_early_init +void board_early_init(void); + +// HSE is 25MHz, run SYS at 120MHz +#define MICROPY_HW_CLK_PLLM (20) +#define MICROPY_HW_CLK_PLLN (192) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (5) +#define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_3) + +// There is an external 32kHz oscillator +#define RTC_ASYNCH_PREDIV (0) +#define RTC_SYNCH_PREDIV (0x7fff) +#define MICROPY_HW_RTC_USE_BYPASS (1) +#define MICROPY_HW_RTC_USE_US (1) +#define MICROPY_HW_RTC_USE_CALOUT (1) + +// SPI flash #1, for R/W storage +#define MICROPY_HW_SOFTQSPI_SCK_LOW(self) (GPIOE->BSRR = (0x10000 << 11)) +#define MICROPY_HW_SOFTQSPI_SCK_HIGH(self) (GPIOE->BSRR = (1 << 11)) +#define MICROPY_HW_SOFTQSPI_NIBBLE_READ(self) ((GPIOE->IDR >> 7) & 0xf) +#define MICROPY_HW_SPIFLASH_SIZE_BITS (16 * 1024 * 1024) +#define MICROPY_HW_SPIFLASH_CS (pyb_pin_QSPI1_CS) +#define MICROPY_HW_SPIFLASH_SCK (pyb_pin_QSPI1_CLK) +#define MICROPY_HW_SPIFLASH_IO0 (pyb_pin_QSPI1_D0) +#define MICROPY_HW_SPIFLASH_IO1 (pyb_pin_QSPI1_D1) +#define MICROPY_HW_SPIFLASH_IO2 (pyb_pin_QSPI1_D2) +#define MICROPY_HW_SPIFLASH_IO3 (pyb_pin_QSPI1_D3) + +// SPI flash #1, block device config +extern const struct _mp_spiflash_config_t spiflash_config; +extern struct _spi_bdev_t spi_bdev; +#define MICROPY_HW_BDEV_IOCTL(op, arg) ( \ + (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \ + (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \ + spi_bdev_ioctl(&spi_bdev, (op), (arg)) \ +) +#define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n)) +#define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n)) + +// SPI flash #2, to be memory mapped +#define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (24) +#define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS) +#define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK) +#define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0) +#define MICROPY_HW_QSPIFLASH_IO1 (pyb_pin_QSPI2_D1) +#define MICROPY_HW_QSPIFLASH_IO2 (pyb_pin_QSPI2_D2) +#define MICROPY_HW_QSPIFLASH_IO3 (pyb_pin_QSPI2_D3) + +// SPI flash #2, block device config +extern const struct _mp_spiflash_config_t spiflash2_config; +extern struct _spi_bdev_t spi_bdev2; + +// UART config +#define MICROPY_HW_UART1_NAME "YA" +#define MICROPY_HW_UART1_TX (pyb_pin_Y1) +#define MICROPY_HW_UART1_RX (pyb_pin_Y2) +#define MICROPY_HW_UART2_TX (pyb_pin_X3) +#define MICROPY_HW_UART2_RX (pyb_pin_X4) +#define MICROPY_HW_UART2_RTS (pyb_pin_X2) +#define MICROPY_HW_UART2_CTS (pyb_pin_X1) +#define MICROPY_HW_UART3_NAME "YB" +#define MICROPY_HW_UART3_TX (pyb_pin_Y9) +#define MICROPY_HW_UART3_RX (pyb_pin_Y10) +#define MICROPY_HW_UART4_NAME "XA" +#define MICROPY_HW_UART4_TX (pyb_pin_X1) +#define MICROPY_HW_UART4_RX (pyb_pin_X2) +#define MICROPY_HW_UART6_TX (pyb_pin_BT_TXD) +#define MICROPY_HW_UART6_RX (pyb_pin_BT_RXD) +#define MICROPY_HW_UART6_RTS (pyb_pin_BT_RTS) +#define MICROPY_HW_UART6_CTS (pyb_pin_BT_CTS) + +// I2C busses +#define MICROPY_HW_I2C1_NAME "X" +#define MICROPY_HW_I2C1_SCL (pyb_pin_X9) +#define MICROPY_HW_I2C1_SDA (pyb_pin_X10) +#define MICROPY_HW_I2C2_NAME "Y" +#define MICROPY_HW_I2C2_SCL (pyb_pin_Y9) +#define MICROPY_HW_I2C2_SDA (pyb_pin_Y10) + +// SPI busses +#define MICROPY_HW_SPI1_NAME "X" +#define MICROPY_HW_SPI1_NSS (pyb_pin_X5) +#define MICROPY_HW_SPI1_SCK (pyb_pin_X6) +#define MICROPY_HW_SPI1_MISO (pyb_pin_X7) +#define MICROPY_HW_SPI1_MOSI (pyb_pin_X8) +#define MICROPY_HW_SPI2_NAME "Y" +#define MICROPY_HW_SPI2_NSS (pyb_pin_Y5) +#define MICROPY_HW_SPI2_SCK (pyb_pin_Y6) +#define MICROPY_HW_SPI2_MISO (pyb_pin_Y7) +#define MICROPY_HW_SPI2_MOSI (pyb_pin_Y8) +#define MICROPY_HW_SPI3_NSS (pyb_pin_W16) +#define MICROPY_HW_SPI3_SCK (pyb_pin_W29) +#define MICROPY_HW_SPI3_MISO (pyb_pin_W50) +#define MICROPY_HW_SPI3_MOSI (pyb_pin_W46) + +// CAN busses +#define MICROPY_HW_CAN1_NAME "X" +#define MICROPY_HW_CAN1_TX (pyb_pin_X10) +#define MICROPY_HW_CAN1_RX (pyb_pin_X9) + +// USRSW is not pulled, and pressing the button makes the input go low. +#define MICROPY_HW_USRSW_PIN (pyb_pin_USR) +#define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// LEDs +#define MICROPY_HW_LED1 (pyb_pin_LED_RED) +#define MICROPY_HW_LED2 (pyb_pin_LED_GREEN) +#define MICROPY_HW_LED3 (pyb_pin_LED_BLUE) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) + +// SD card +#define MICROPY_HW_SDMMC2_CK (pyb_pin_SD_CK) +#define MICROPY_HW_SDMMC2_CMD (pyb_pin_SD_CMD) +#define MICROPY_HW_SDMMC2_D0 (pyb_pin_SD_D0) +#define MICROPY_HW_SDMMC2_D1 (pyb_pin_SD_D1) +#define MICROPY_HW_SDMMC2_D2 (pyb_pin_SD_D2) +#define MICROPY_HW_SDMMC2_D3 (pyb_pin_SD_D3) +#define MICROPY_HW_SDCARD_DETECT_PIN (pyb_pin_SD_SW) +#define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) +#define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) +#define MICROPY_HW_SDCARD_MOUNT_AT_BOOT (0) + +// USB config +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_HS (1) +#define MICROPY_HW_USB_HS_IN_FS (1) +#define MICROPY_HW_USB_MAIN_DEV (USB_PHY_HS_ID) + +/******************************************************************************/ +// Bootloader configuration + +#define MBOOT_USB_AUTODETECT_PORT (1) +#define MBOOT_FSLOAD (1) + +#define MBOOT_I2C_PERIPH_ID 1 +#define MBOOT_I2C_SCL (pin_B8) +#define MBOOT_I2C_SDA (pin_B9) +#define MBOOT_I2C_ALTFUNC (4) + +#define MBOOT_SPIFLASH_ADDR (0x80000000) +#define MBOOT_SPIFLASH_BYTE_SIZE (64 * 32 * 1024) +#define MBOOT_SPIFLASH_LAYOUT "/0x80000000/64*32Kg" +#define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (32 / 4) +#define MBOOT_SPIFLASH_SPIFLASH (&spi_bdev.spiflash) +#define MBOOT_SPIFLASH_CONFIG (&spiflash_config) + +#define MBOOT_SPIFLASH2_ADDR (0x90000000) +#define MBOOT_SPIFLASH2_BYTE_SIZE (64 * 32 * 1024) +#define MBOOT_SPIFLASH2_LAYOUT "/0x90000000/64*32Kg" +#define MBOOT_SPIFLASH2_ERASE_BLOCKS_PER_PAGE (32 / 4) +#define MBOOT_SPIFLASH2_SPIFLASH (&spi_bdev2.spiflash) +#define MBOOT_SPIFLASH2_CONFIG (&spiflash2_config) + +#define MBOOT_BOARD_EARLY_INIT mboot_board_early_init +void mboot_board_early_init(void); diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk new file mode 100644 index 0000000000000..87e397065618c --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk @@ -0,0 +1,10 @@ +# MCU settings +MCU_SERIES = f7 +CMSIS_MCU = STM32F722xx +MICROPY_FLOAT_IMPL = single +AF_FILE = boards/stm32f722_af.csv +LD_FILES = boards/PYBD_SF2/f722_qspi.ld +TEXT0_ADDR = 0x08008000 + +# MicroPython settings +MICROPY_PY_LWIP = 1 diff --git a/ports/stm32/boards/PYBD_SF2/pins.csv b/ports/stm32/boards/PYBD_SF2/pins.csv new file mode 100644 index 0000000000000..c11f3fe90624d --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/pins.csv @@ -0,0 +1,189 @@ +W3,PE3 +W5,PA11 +W5B,PI0 +W6,PA5 +W7,PA4 +W7B,PG7 +W8,PB11 +W9,PA12 +W9B,PI1 +W10,PA6 +W11,PA3 +W12,PB10 +W14,PA7 +W15,PA2 +W16,PA15 +W17,PA1 +W18,PD3 +W19,PA0 +W20,PD0 +W21,PC14 +W22,PE12 +W22B,PF6 +W22C,PF7 +W22D,PF10 +W23,PE1 +W24,PC1 +W25,PE0 +W26,PC13 +W27,PA8 +W27B,PC6 +W28,PE6 +W29,PB3 +W30,PE5 +W32,PE4 +W33,PH2 +W34,PH3 +W43,PB0 +W43B,PC0 +W43C,PF9 +W43D,PF11 +W45,PB12 +W45B,PE14 +W45C,PH8 +W46,PB5 +W47,PC5 +W47B,PF14 +W49,PB13 +W50,PB4 +W51,PC4 +W51B,PF15 +W52,PA10 +W53,PC2 +W53B,PF8 +W54,PA9 +W55,PB9 +W56,PA14 +W57,PC3 +W57B,PF13 +W58,PG11 +W59,PB8 +W60,PG12 +W61,PB7 +W62,PD7 +W63,PB1 +W63B,PD9 +W64,PD6 +W65,PD8 +W66,PG9 +W67,PA13 +W68,PG10 +W70,PB14 +W71,PE15 +W72,PB15 +W73,PH6 +W74,PH7 +X1,PA0 +X2,PA1 +X3,PA2 +X4,PA3 +X5,PA4 +X5B,PG7 +X6,PA5 +X7,PA6 +X8,PA7 +X9,PB8 +X10,PB9 +X11,PC4 +X11B,PF15 +X12,PC5 +X12B,PF14 +Y1,PA9 +Y2,PA10 +Y3,PB4 +Y4,PB5 +Y5,PB12 +Y5B,PE14 +Y5C,PH8 +Y6,PB13 +Y7,PC2 +Y7B,PF8 +Y8,PC3 +Y8B,PF13 +Y9,PB10 +Y10,PB11 +Y11,PB0 +Y11B,PC0 +Y11C,PF9 +Y11D,PF11 +Y12,PB1 +Y12B,PD9 +EN_3V3,PF2 +PULL_SCL,PF1 +PULL_SDA,PH5 +LED_RED,PF3 +LED_GREEN,PF4 +LED_BLUE,PF5 +USR,PA13 +USB_DM,PA11 +USB_DP,PA12 +USB_HS_DM,PB14 +USB_HS_DP,PB15 +-QSPI1_CS,PE13 +-QSPI1_CLK,PE11 +-QSPI1_D0,PE7 +-QSPI1_D1,PE8 +-QSPI1_D2,PE9 +-QSPI1_D3,PE10 +-QSPI2_CS,PB6 +-QSPI2_CLK,PB2 +-QSPI2_D0,PD11 +-QSPI2_D1,PD12 +-QSPI2_D2,PE2 +-QSPI2_D3,PD13 +-SD_D0,PG9 +-SD_D1,PG10 +-SD_D2,PG11 +-SD_D3,PG12 +-SD_CMD,PD7 +-SD_CK,PD6 +SD_SW,PA14 +-WL_REG_ON,PD4 +-WL_HOST_WAKE,PI8 +-WL_RFSW_VDD,PI9 +-WL_GPIO_1,PI11 +-WL_GPIO_2,PI7 +-WL_GPIO_4,PI9 +-WL_SDIO_0,PC8 +-WL_SDIO_1,PC9 +-WL_SDIO_2,PC10 +-WL_SDIO_3,PC11 +-WL_SDIO_CMD,PD2 +-WL_SDIO_CLK,PC12 +-BT_RXD,PC7 +-BT_TXD,PG14 +-BT_CTS,PG13 +-BT_RTS,PG8 +-BT_GPIO_3,PG15 +-BT_GPIO_4,PI5 +-BT_GPIO_5,PI4 +-BT_PCM_SYNC,PE4 +-BT_PCM_IN,PE6 +-BT_PCM_OUT,PE3 +-BT_PCM_CLK,PE5 +-BT_I2C_D0,PI10 +-BT_REG_ON,PI6 +-BT_HOST_WAKE,PD10 +-BT_DEV_WAKE,PD5 +,PD1 +,PD14 +,PD15 +,PF0 +,PF12 +,PG0 +,PG1 +,PG2 +,PG3 +,PG4 +,PG5 +,PG6 +,PH4 +,PH9 +,PH10 +,PH11 +,PH12 +,PH13 +,PH14 +,PH15 +,PI2 +,PI3 diff --git a/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h b/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h new file mode 100644 index 0000000000000..c820dafc44d72 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h @@ -0,0 +1,88 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H + +// Include various HAL modules for convenience +#include "stm32f7xx_hal_dma.h" +#include "stm32f7xx_hal_adc.h" +#include "stm32f7xx_hal_can.h" +#include "stm32f7xx_hal_cortex.h" +#include "stm32f7xx_hal_dac.h" +#include "stm32f7xx_hal_flash.h" +#include "stm32f7xx_hal_gpio.h" +#include "stm32f7xx_hal_i2c.h" +#include "stm32f7xx_hal_mmc.h" +#include "stm32f7xx_hal_pcd.h" +#include "stm32f7xx_hal_pwr.h" +#include "stm32f7xx_hal_rcc.h" +#include "stm32f7xx_hal_rtc.h" +#include "stm32f7xx_hal_sd.h" +#include "stm32f7xx_hal_spi.h" +#include "stm32f7xx_hal_tim.h" +#include "stm32f7xx_hal_uart.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED + +// Oscillator values in Hz +#define HSI_VALUE (16000000) +#define HSE_VALUE ((uint32_t)25000000) +#define LSI_VALUE (32000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (5000) +#define LSE_STARTUP_TIMEOUT (5000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// No RTOS is used +#define USE_RTOS 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H diff --git a/ports/stm32/boards/PYBD_SF3/bdev.c b/ports/stm32/boards/PYBD_SF3/bdev.c new file mode 100644 index 0000000000000..b43028c06b4a6 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF3/bdev.c @@ -0,0 +1 @@ +#include "boards/PYBD_SF2/bdev.c" diff --git a/ports/stm32/boards/PYBD_SF3/board_init.c b/ports/stm32/boards/PYBD_SF3/board_init.c new file mode 100644 index 0000000000000..c7a9f28006be3 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF3/board_init.c @@ -0,0 +1 @@ +#include "boards/PYBD_SF2/board_init.c" diff --git a/ports/stm32/boards/PYBD_SF3/mpconfigboard.h b/ports/stm32/boards/PYBD_SF3/mpconfigboard.h new file mode 100644 index 0000000000000..8c79e6fe64313 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF3/mpconfigboard.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Take PYBD_SF2 as base configuration +#include "boards/PYBD_SF2/mpconfigboard.h" + +#undef MICROPY_HW_BOARD_NAME +#undef MICROPY_HW_MCU_NAME + +#define MICROPY_HW_BOARD_NAME "PYBD-SF3W" +#define MICROPY_HW_MCU_NAME "STM32F733IEK" diff --git a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk new file mode 100644 index 0000000000000..6104ed247591e --- /dev/null +++ b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk @@ -0,0 +1,13 @@ +# MCU settings +MCU_SERIES = f7 +CMSIS_MCU = STM32F733xx +MICROPY_FLOAT_IMPL = single +AF_FILE = boards/stm32f722_af.csv +LD_FILES = boards/PYBD_SF2/f722_qspi.ld +TEXT0_ADDR = 0x08008000 +TEXT1_ADDR = 0x90000000 +TEXT0_SECTIONS = .isr_vector .text .data +TEXT1_SECTIONS = .text_ext + +# MicroPython settings +MICROPY_PY_LWIP = 1 diff --git a/ports/stm32/boards/PYBD_SF3/pins.csv b/ports/stm32/boards/PYBD_SF3/pins.csv new file mode 100644 index 0000000000000..c11f3fe90624d --- /dev/null +++ b/ports/stm32/boards/PYBD_SF3/pins.csv @@ -0,0 +1,189 @@ +W3,PE3 +W5,PA11 +W5B,PI0 +W6,PA5 +W7,PA4 +W7B,PG7 +W8,PB11 +W9,PA12 +W9B,PI1 +W10,PA6 +W11,PA3 +W12,PB10 +W14,PA7 +W15,PA2 +W16,PA15 +W17,PA1 +W18,PD3 +W19,PA0 +W20,PD0 +W21,PC14 +W22,PE12 +W22B,PF6 +W22C,PF7 +W22D,PF10 +W23,PE1 +W24,PC1 +W25,PE0 +W26,PC13 +W27,PA8 +W27B,PC6 +W28,PE6 +W29,PB3 +W30,PE5 +W32,PE4 +W33,PH2 +W34,PH3 +W43,PB0 +W43B,PC0 +W43C,PF9 +W43D,PF11 +W45,PB12 +W45B,PE14 +W45C,PH8 +W46,PB5 +W47,PC5 +W47B,PF14 +W49,PB13 +W50,PB4 +W51,PC4 +W51B,PF15 +W52,PA10 +W53,PC2 +W53B,PF8 +W54,PA9 +W55,PB9 +W56,PA14 +W57,PC3 +W57B,PF13 +W58,PG11 +W59,PB8 +W60,PG12 +W61,PB7 +W62,PD7 +W63,PB1 +W63B,PD9 +W64,PD6 +W65,PD8 +W66,PG9 +W67,PA13 +W68,PG10 +W70,PB14 +W71,PE15 +W72,PB15 +W73,PH6 +W74,PH7 +X1,PA0 +X2,PA1 +X3,PA2 +X4,PA3 +X5,PA4 +X5B,PG7 +X6,PA5 +X7,PA6 +X8,PA7 +X9,PB8 +X10,PB9 +X11,PC4 +X11B,PF15 +X12,PC5 +X12B,PF14 +Y1,PA9 +Y2,PA10 +Y3,PB4 +Y4,PB5 +Y5,PB12 +Y5B,PE14 +Y5C,PH8 +Y6,PB13 +Y7,PC2 +Y7B,PF8 +Y8,PC3 +Y8B,PF13 +Y9,PB10 +Y10,PB11 +Y11,PB0 +Y11B,PC0 +Y11C,PF9 +Y11D,PF11 +Y12,PB1 +Y12B,PD9 +EN_3V3,PF2 +PULL_SCL,PF1 +PULL_SDA,PH5 +LED_RED,PF3 +LED_GREEN,PF4 +LED_BLUE,PF5 +USR,PA13 +USB_DM,PA11 +USB_DP,PA12 +USB_HS_DM,PB14 +USB_HS_DP,PB15 +-QSPI1_CS,PE13 +-QSPI1_CLK,PE11 +-QSPI1_D0,PE7 +-QSPI1_D1,PE8 +-QSPI1_D2,PE9 +-QSPI1_D3,PE10 +-QSPI2_CS,PB6 +-QSPI2_CLK,PB2 +-QSPI2_D0,PD11 +-QSPI2_D1,PD12 +-QSPI2_D2,PE2 +-QSPI2_D3,PD13 +-SD_D0,PG9 +-SD_D1,PG10 +-SD_D2,PG11 +-SD_D3,PG12 +-SD_CMD,PD7 +-SD_CK,PD6 +SD_SW,PA14 +-WL_REG_ON,PD4 +-WL_HOST_WAKE,PI8 +-WL_RFSW_VDD,PI9 +-WL_GPIO_1,PI11 +-WL_GPIO_2,PI7 +-WL_GPIO_4,PI9 +-WL_SDIO_0,PC8 +-WL_SDIO_1,PC9 +-WL_SDIO_2,PC10 +-WL_SDIO_3,PC11 +-WL_SDIO_CMD,PD2 +-WL_SDIO_CLK,PC12 +-BT_RXD,PC7 +-BT_TXD,PG14 +-BT_CTS,PG13 +-BT_RTS,PG8 +-BT_GPIO_3,PG15 +-BT_GPIO_4,PI5 +-BT_GPIO_5,PI4 +-BT_PCM_SYNC,PE4 +-BT_PCM_IN,PE6 +-BT_PCM_OUT,PE3 +-BT_PCM_CLK,PE5 +-BT_I2C_D0,PI10 +-BT_REG_ON,PI6 +-BT_HOST_WAKE,PD10 +-BT_DEV_WAKE,PD5 +,PD1 +,PD14 +,PD15 +,PF0 +,PF12 +,PG0 +,PG1 +,PG2 +,PG3 +,PG4 +,PG5 +,PG6 +,PH4 +,PH9 +,PH10 +,PH11 +,PH12 +,PH13 +,PH14 +,PH15 +,PI2 +,PI3 diff --git a/ports/stm32/boards/PYBD_SF3/stm32f7xx_hal_conf.h b/ports/stm32/boards/PYBD_SF3/stm32f7xx_hal_conf.h new file mode 100644 index 0000000000000..0f178c2ba310f --- /dev/null +++ b/ports/stm32/boards/PYBD_SF3/stm32f7xx_hal_conf.h @@ -0,0 +1 @@ +#include "boards/PYBD_SF2/stm32f7xx_hal_conf.h" diff --git a/ports/stm32/boards/PYBD_SF6/bdev.c b/ports/stm32/boards/PYBD_SF6/bdev.c new file mode 100644 index 0000000000000..b43028c06b4a6 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF6/bdev.c @@ -0,0 +1 @@ +#include "boards/PYBD_SF2/bdev.c" diff --git a/ports/stm32/boards/PYBD_SF6/board_init.c b/ports/stm32/boards/PYBD_SF6/board_init.c new file mode 100644 index 0000000000000..c7a9f28006be3 --- /dev/null +++ b/ports/stm32/boards/PYBD_SF6/board_init.c @@ -0,0 +1 @@ +#include "boards/PYBD_SF2/board_init.c" diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld new file mode 100644 index 0000000000000..d910438a7ed9f --- /dev/null +++ b/ports/stm32/boards/PYBD_SF6/f767.ld @@ -0,0 +1,96 @@ +/* + Linker script for PYBD with STM32F767 + + Memory layout for mboot configuration (this here describes the app part): + + FLASH_APP .isr_vector + FLASH_APP .text + FLASH_APP .data + + RAM .data + RAM .bss + RAM .heap + RAM .stack +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K + FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0, 32K */ + FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 2016K /* sectors 1-11 3x32K 1*128K 7*256K */ + FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 2048K /* external QSPI */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 512K /* DTCM=128k, SRAM1=368K, SRAM2=16K */ +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* Define tho top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _ram_end - 24K; /* 24k stack */ + +ENTRY(Reset_Handler) + +/* Define output sections */ +SECTIONS +{ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } >FLASH_APP + + .text : + { + . = ALIGN(4); + *(.text*) + *(.rodata*) + . = ALIGN(4); + _etext = .; + } >FLASH_APP + + _sidata = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data*) + . = ALIGN(4); + _edata = .; + } >RAM AT> FLASH_APP + + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >RAM + + .heap : + { + . = ALIGN(4); + . = . + _minimum_heap_size; + . = ALIGN(4); + } >RAM + + .stack : + { + . = ALIGN(4); + . = . + _minimum_stack_size; + . = ALIGN(4); + } >RAM +} diff --git a/ports/stm32/boards/PYBD_SF6/mpconfigboard.h b/ports/stm32/boards/PYBD_SF6/mpconfigboard.h new file mode 100644 index 0000000000000..cbfbe39945daf --- /dev/null +++ b/ports/stm32/boards/PYBD_SF6/mpconfigboard.h @@ -0,0 +1,66 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Take PYBD_SF2 as base configuration +#include "boards/PYBD_SF2/mpconfigboard.h" + +#undef MICROPY_HW_BOARD_NAME +#undef MICROPY_HW_MCU_NAME +#undef MICROPY_HW_CLK_PLLM +#undef MICROPY_HW_CLK_PLLN +#undef MICROPY_HW_CLK_PLLP +#undef MICROPY_HW_CLK_PLLQ +#undef MICROPY_HW_FLASH_LATENCY + +#define MICROPY_HW_BOARD_NAME "PYBD-SF6W" +#define MICROPY_HW_MCU_NAME "STM32F767IIK" + +// HSE is 25MHz, run SYS at 144MHz +#define MICROPY_HW_CLK_PLLM (25) +#define MICROPY_HW_CLK_PLLN (288) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (6) +#define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_4) + +// Extra UART config +#define MICROPY_HW_UART7_TX (pyb_pin_W16) +#define MICROPY_HW_UART7_RX (pyb_pin_W22B) + +// Extra CAN busses +#define MICROPY_HW_CAN2_NAME "Y" +#define MICROPY_HW_CAN2_TX (pyb_pin_Y6) +#define MICROPY_HW_CAN2_RX (pyb_pin_Y5) + +// Ethernet via RMII +#define MICROPY_HW_ETH_MDC (pyb_pin_W24) +#define MICROPY_HW_ETH_MDIO (pyb_pin_W15) +#define MICROPY_HW_ETH_RMII_REF_CLK (pyb_pin_W17) +#define MICROPY_HW_ETH_RMII_CRS_DV (pyb_pin_W14) +#define MICROPY_HW_ETH_RMII_RXD0 (pyb_pin_W51) +#define MICROPY_HW_ETH_RMII_RXD1 (pyb_pin_W47) +#define MICROPY_HW_ETH_RMII_TX_EN (pyb_pin_W8) +#define MICROPY_HW_ETH_RMII_TXD0 (pyb_pin_W45) +#define MICROPY_HW_ETH_RMII_TXD1 (pyb_pin_W49) diff --git a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk new file mode 100644 index 0000000000000..0288b9142c37e --- /dev/null +++ b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk @@ -0,0 +1,10 @@ +# MCU settings +MCU_SERIES = f7 +CMSIS_MCU = STM32F767xx +MICROPY_FLOAT_IMPL = double +AF_FILE = boards/stm32f767_af.csv +LD_FILES = boards/PYBD_SF6/f767.ld +TEXT0_ADDR = 0x08008000 + +# MicroPython settings +MICROPY_PY_LWIP = 1 diff --git a/ports/stm32/boards/PYBD_SF6/pins.csv b/ports/stm32/boards/PYBD_SF6/pins.csv new file mode 100644 index 0000000000000..c11f3fe90624d --- /dev/null +++ b/ports/stm32/boards/PYBD_SF6/pins.csv @@ -0,0 +1,189 @@ +W3,PE3 +W5,PA11 +W5B,PI0 +W6,PA5 +W7,PA4 +W7B,PG7 +W8,PB11 +W9,PA12 +W9B,PI1 +W10,PA6 +W11,PA3 +W12,PB10 +W14,PA7 +W15,PA2 +W16,PA15 +W17,PA1 +W18,PD3 +W19,PA0 +W20,PD0 +W21,PC14 +W22,PE12 +W22B,PF6 +W22C,PF7 +W22D,PF10 +W23,PE1 +W24,PC1 +W25,PE0 +W26,PC13 +W27,PA8 +W27B,PC6 +W28,PE6 +W29,PB3 +W30,PE5 +W32,PE4 +W33,PH2 +W34,PH3 +W43,PB0 +W43B,PC0 +W43C,PF9 +W43D,PF11 +W45,PB12 +W45B,PE14 +W45C,PH8 +W46,PB5 +W47,PC5 +W47B,PF14 +W49,PB13 +W50,PB4 +W51,PC4 +W51B,PF15 +W52,PA10 +W53,PC2 +W53B,PF8 +W54,PA9 +W55,PB9 +W56,PA14 +W57,PC3 +W57B,PF13 +W58,PG11 +W59,PB8 +W60,PG12 +W61,PB7 +W62,PD7 +W63,PB1 +W63B,PD9 +W64,PD6 +W65,PD8 +W66,PG9 +W67,PA13 +W68,PG10 +W70,PB14 +W71,PE15 +W72,PB15 +W73,PH6 +W74,PH7 +X1,PA0 +X2,PA1 +X3,PA2 +X4,PA3 +X5,PA4 +X5B,PG7 +X6,PA5 +X7,PA6 +X8,PA7 +X9,PB8 +X10,PB9 +X11,PC4 +X11B,PF15 +X12,PC5 +X12B,PF14 +Y1,PA9 +Y2,PA10 +Y3,PB4 +Y4,PB5 +Y5,PB12 +Y5B,PE14 +Y5C,PH8 +Y6,PB13 +Y7,PC2 +Y7B,PF8 +Y8,PC3 +Y8B,PF13 +Y9,PB10 +Y10,PB11 +Y11,PB0 +Y11B,PC0 +Y11C,PF9 +Y11D,PF11 +Y12,PB1 +Y12B,PD9 +EN_3V3,PF2 +PULL_SCL,PF1 +PULL_SDA,PH5 +LED_RED,PF3 +LED_GREEN,PF4 +LED_BLUE,PF5 +USR,PA13 +USB_DM,PA11 +USB_DP,PA12 +USB_HS_DM,PB14 +USB_HS_DP,PB15 +-QSPI1_CS,PE13 +-QSPI1_CLK,PE11 +-QSPI1_D0,PE7 +-QSPI1_D1,PE8 +-QSPI1_D2,PE9 +-QSPI1_D3,PE10 +-QSPI2_CS,PB6 +-QSPI2_CLK,PB2 +-QSPI2_D0,PD11 +-QSPI2_D1,PD12 +-QSPI2_D2,PE2 +-QSPI2_D3,PD13 +-SD_D0,PG9 +-SD_D1,PG10 +-SD_D2,PG11 +-SD_D3,PG12 +-SD_CMD,PD7 +-SD_CK,PD6 +SD_SW,PA14 +-WL_REG_ON,PD4 +-WL_HOST_WAKE,PI8 +-WL_RFSW_VDD,PI9 +-WL_GPIO_1,PI11 +-WL_GPIO_2,PI7 +-WL_GPIO_4,PI9 +-WL_SDIO_0,PC8 +-WL_SDIO_1,PC9 +-WL_SDIO_2,PC10 +-WL_SDIO_3,PC11 +-WL_SDIO_CMD,PD2 +-WL_SDIO_CLK,PC12 +-BT_RXD,PC7 +-BT_TXD,PG14 +-BT_CTS,PG13 +-BT_RTS,PG8 +-BT_GPIO_3,PG15 +-BT_GPIO_4,PI5 +-BT_GPIO_5,PI4 +-BT_PCM_SYNC,PE4 +-BT_PCM_IN,PE6 +-BT_PCM_OUT,PE3 +-BT_PCM_CLK,PE5 +-BT_I2C_D0,PI10 +-BT_REG_ON,PI6 +-BT_HOST_WAKE,PD10 +-BT_DEV_WAKE,PD5 +,PD1 +,PD14 +,PD15 +,PF0 +,PF12 +,PG0 +,PG1 +,PG2 +,PG3 +,PG4 +,PG5 +,PG6 +,PH4 +,PH9 +,PH10 +,PH11 +,PH12 +,PH13 +,PH14 +,PH15 +,PI2 +,PI3 diff --git a/ports/stm32/boards/PYBD_SF6/stm32f7xx_hal_conf.h b/ports/stm32/boards/PYBD_SF6/stm32f7xx_hal_conf.h new file mode 100644 index 0000000000000..0f178c2ba310f --- /dev/null +++ b/ports/stm32/boards/PYBD_SF6/stm32f7xx_hal_conf.h @@ -0,0 +1 @@ +#include "boards/PYBD_SF2/stm32f7xx_hal_conf.h" From 84f1067f7fa3d61bd9e732eb46e8c52ff3d03be2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 May 2019 22:47:00 +1000 Subject: [PATCH 0136/1299] travis: Build PYBD_SF2 board as part of the stm32 job. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0ba9a002233fe..4ec5069050176 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ jobs: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 + - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32F769DISC - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32L476DISC From 8e3af7d4c80bfd9047431eb62804ecd4f60cdb9f Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Sat, 4 May 2019 19:00:35 -0600 Subject: [PATCH 0137/1299] esp32: Add machine.SDCard class using built-in HW SD/MMC controller. This adds support for SD cards using the ESP32's built-in hardware SD/MMC host controller, over either the SDIO bus or SPI. The class is available as machine.SDCard and using it can be as simple as: uos.mount(machine.SDCard(), '/sd') --- ports/esp32/Makefile | 20 ++ ports/esp32/machine_sdcard.c | 391 +++++++++++++++++++++++++++++++++++ ports/esp32/modmachine.c | 3 + ports/esp32/modmachine.h | 1 + ports/esp32/mpconfigport.h | 1 + 5 files changed, 416 insertions(+) create mode 100644 ports/esp32/machine_sdcard.c diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index ea90c9f3f5a9d..98ad196c1d235 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -111,6 +111,7 @@ INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include INC_ESPCOMP += -I$(ESPCOMP)/app_update/include INC_ESPCOMP += -I$(ESPCOMP)/pthread/include INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include +INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include # these flags are common to C and C++ compilation CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ @@ -192,6 +193,7 @@ SRC_C = \ machine_wdt.c \ mpthreadport.c \ machine_rtc.c \ + machine_sdcard.c \ $(SRC_MOD) EXTMOD_SRC_C = $(addprefix extmod/,\ @@ -257,6 +259,11 @@ ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\ ledc.o \ gpio.o \ timer.o \ + sdmmc_host.o \ + sdmmc_transaction.o \ + sdspi_crc.o \ + sdspi_host.o \ + sdspi_transaction.o \ spi_master.o \ spi_common.o \ rtc_module.o \ @@ -329,6 +336,7 @@ ESPIDF_SOC_O = $(addprefix $(ESPCOMP)/soc/,\ esp32/rtc_sleep.o \ esp32/rtc_time.o \ esp32/rtc_wdt.o \ + esp32/sdmmc_periph.o \ esp32/soc_memory_layout.o \ esp32/spi_periph.o \ src/memory_layout_utils.o \ @@ -665,6 +673,15 @@ ESPIDF_WPA_SUPPLICANT_O = $(addprefix $(ESPCOMP)/wpa_supplicant/,\ port/os_xtensa.o \ ) +ESPIDF_SDMMC_O = $(addprefix $(ESPCOMP)/sdmmc/,\ + sdmmc_cmd.o \ + sdmmc_common.o \ + sdmmc_init.o \ + sdmmc_mmc.o \ + sdmmc_sd.o \ + sdmmc_io.o \ + ) + OBJ_ESPIDF = OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_DRIVER_O)) @@ -693,6 +710,7 @@ OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SMARTCONFIG_ACK_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SPI_FLASH_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ULP_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_WPA_SUPPLICANT_O)) +OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SDMMC_O)) $(OBJ_ESPIDF): $(SDKCONFIG_H) @@ -723,6 +741,7 @@ LIB_ESPIDF += ulp LIB_ESPIDF += lwip LIB_ESPIDF += mbedtls LIB_ESPIDF += wpa_supplicant +LIB_ESPIDF += sdmmc BUILD_ESPIDF_LIB = $(BUILD)/esp-idf @@ -763,6 +782,7 @@ $(eval $(call gen_espidf_lib_rule,ulp,$(ESPIDF_ULP_O))) $(eval $(call gen_espidf_lib_rule,lwip,$(ESPIDF_LWIP_O))) $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) +$(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) LIB = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c new file mode 100644 index 0000000000000..633d4031d6ec1 --- /dev/null +++ b/ports/esp32/machine_sdcard.c @@ -0,0 +1,391 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Nicko van Someren + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/runtime.h" +#include "py/mphal.h" +#include "py/mperrno.h" +#include "extmod/vfs_fat.h" + +#include "driver/sdmmc_host.h" +#include "driver/sdspi_host.h" +#include "sdmmc_cmd.h" +#include "esp_log.h" + +#define DEBUG 0 +#if DEBUG +#define DEBUG_printf(...) ESP_LOGI("modsdcard", __VA_ARGS__) +#else +#define DEBUG_printf(...) (void)0 +#endif + +// +// There are three layers of abstraction: host, slot and card. +// Creating an SD Card object will initialise the host and slot. +// Cards gets initialised by ioctl op==1 and de-inited by ioctl 2 +// Hosts are de-inited in __del__. Slots do not need de-initing. +// + +// Currently the ESP32 Library doesn't support MMC cards, so +// we don't enable on MICROPY_HW_ENABLE_MMCARD. +#if MICROPY_HW_ENABLE_SDCARD + +// Forward declaration +const mp_obj_type_t machine_sdcard_type; + +typedef struct _sdcard_obj_t { + mp_obj_base_t base; + mp_int_t flags; + sdmmc_host_t host; + // The card structure duplicates the host. It's not clear if we + // can avoid this given the way that it is copied. + sdmmc_card_t card; +} sdcard_card_obj_t; + +#define SDCARD_CARD_FLAGS_HOST_INIT_DONE 0x01 +#define SDCARD_CARD_FLAGS_CARD_INIT_DONE 0x02 + +#define _SECTOR_SIZE(self) (self->card.csd.sector_size) + +STATIC esp_err_t check_esp_err(esp_err_t code) { + switch(code) { + case ESP_OK: + return ESP_OK; + case ESP_ERR_NO_MEM: + code = MP_ENOMEM; + break; + case ESP_ERR_TIMEOUT: + code = MP_ETIMEDOUT; + break; + case ESP_ERR_NOT_SUPPORTED: + code = MP_EOPNOTSUPP; + break; + } + + mp_raise_OSError(code); +} + +STATIC gpio_num_t pin_or_int(const mp_obj_t arg) { + if (mp_obj_is_small_int(arg)) { + return MP_OBJ_SMALL_INT_VALUE(arg); + } else { + // This raises a value error if the argument is not a Pin. + return machine_pin_get_id(arg); + } +} + +#define SET_CONFIG_PIN(config, pin_var, arg_id) \ + if (arg_vals[arg_id].u_obj != mp_const_none) \ + config.pin_var = pin_or_int(arg_vals[arg_id].u_obj) + +STATIC esp_err_t sdcard_ensure_card_init(sdcard_card_obj_t *self, bool force) { + if (force || !(self->flags & SDCARD_CARD_FLAGS_CARD_INIT_DONE)) { + DEBUG_printf(" Calling card init"); + + esp_err_t err = sdmmc_card_init(&(self->host), &(self->card)); + if (err == ESP_OK) { + self->flags |= SDCARD_CARD_FLAGS_CARD_INIT_DONE; + } else { + self->flags &= ~SDCARD_CARD_FLAGS_CARD_INIT_DONE; + } + DEBUG_printf(" Card init returned: %i", err); + + return err; + } else { + return ESP_OK; + } +} + +/******************************************************************************/ +// MicroPython bindings +// +// Expose the SD card or MMC as an object with the block protocol. + +// Create a new SDCard object +// The driver supports either the host SD/MMC controller (default) or SPI mode +// In both cases there are two "slots". Slot 0 on the SD/MMC controller is +// typically tied up with the flash interface in most ESP32 modules but in +// theory supports 1, 4 or 8-bit transfers. Slot 1 supports only 1 and 4-bit +// transfers. Only 1-bit is supported on the SPI interfaces. +// card = SDCard(slot=1, width=None, present_pin=None, wp_pin=None) + +STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + enum { + ARG_slot, + ARG_width, + ARG_cd, + ARG_wp, + ARG_miso, + ARG_mosi, + ARG_sck, + ARG_cs, + }; + STATIC const mp_arg_t allowed_args[] = { + { MP_QSTR_slot, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_cd, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_wp, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + // These are only needed if using SPI mode + { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)]; + mp_map_t kw_args; + + DEBUG_printf("Making new SDCard:n"); + DEBUG_printf(" Unpacking arguments"); + + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + + mp_arg_parse_all(n_args, args, &kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals); + + DEBUG_printf(" slot=%d, width=%d, cd=%p, wp=%p", + arg_vals[ARG_slot].u_int, arg_vals[ARG_width].u_int, + arg_vals[ARG_cd].u_obj, arg_vals[ARG_wp].u_obj); + + DEBUG_printf(" miso=%p, mosi=%p, sck=%p, cs=%p", + arg_vals[ARG_miso].u_obj, arg_vals[ARG_mosi].u_obj, + arg_vals[ARG_sck].u_obj, arg_vals[ARG_cs].u_obj); + + int slot_num = arg_vals[ARG_slot].u_int; + if (slot_num < 0 || slot_num > 3) { + mp_raise_ValueError("Slot number must be between 0 and 3 inclusive"); + } + + // Slots 0 and 1 are native SD/MMC, slots 2 and 3 are SPI + bool is_spi = (slot_num >= 2); + if (is_spi) { + slot_num -= 2; + } + + DEBUG_printf(" Setting up host configuration"); + + sdcard_card_obj_t *self = m_new_obj_with_finaliser(sdcard_card_obj_t); + self->base.type = &machine_sdcard_type; + self->flags = 0; + // Note that these defaults are macros that expand to structure + // constants so we can't directly assign them to fields. + if (is_spi) { + sdmmc_host_t _temp_host = SDSPI_HOST_DEFAULT(); + self->host = _temp_host; + } else { + sdmmc_host_t _temp_host = SDMMC_HOST_DEFAULT(); + self->host = _temp_host; + } + + if (is_spi) { + self->host.slot = slot_num ? HSPI_HOST : VSPI_HOST; + slot_num -= 2; + } + + DEBUG_printf(" Calling host.init()"); + + check_esp_err(self->host.init()); + self->flags |= SDCARD_CARD_FLAGS_HOST_INIT_DONE; + + if (is_spi) { + // SPI interface + STATIC const sdspi_slot_config_t slot_defaults[2] = { + { + .gpio_miso = GPIO_NUM_19, + .gpio_mosi = GPIO_NUM_23, + .gpio_sck = GPIO_NUM_18, + .gpio_cs = GPIO_NUM_5, + .gpio_cd = SDSPI_SLOT_NO_CD, + .gpio_wp = SDSPI_SLOT_NO_WP, + .dma_channel = 2 + }, + SDSPI_SLOT_CONFIG_DEFAULT() }; + + DEBUG_printf(" Setting up SPI slot configuration"); + sdspi_slot_config_t slot_config = slot_defaults[slot_num]; + + SET_CONFIG_PIN(slot_config, gpio_cd, ARG_cd); + SET_CONFIG_PIN(slot_config, gpio_wp, ARG_wp); + SET_CONFIG_PIN(slot_config, gpio_miso, ARG_miso); + SET_CONFIG_PIN(slot_config, gpio_mosi, ARG_mosi); + SET_CONFIG_PIN(slot_config, gpio_sck, ARG_sck); + SET_CONFIG_PIN(slot_config, gpio_cs, ARG_cs); + + DEBUG_printf(" Calling init_slot()"); + check_esp_err(sdspi_host_init_slot(self->host.slot, &slot_config)); + } else { + // SD/MMC interface + DEBUG_printf(" Setting up SDMMC slot configuration"); + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + + // Stronger external pull-ups are still needed but apparently + // it is a good idea to set the internal pull-ups anyway. + // slot_config.flags = SDMMC_SLOT_FLAG_INTERNAL_PULLUP; + + SET_CONFIG_PIN(slot_config, gpio_cd, ARG_cd); + SET_CONFIG_PIN(slot_config, gpio_wp, ARG_wp); + + int width = arg_vals[ARG_width].u_int; + if (width == 1 || width == 4 || (width == 8 && slot_num == 0)) { + slot_config.width = width; + } else { + mp_raise_ValueError("Width must be 1 or 4 (or 8 on slot 0)"); + } + + DEBUG_printf(" Calling init_slot()"); + check_esp_err(sdmmc_host_init_slot(self->host.slot, &slot_config)); + } + + DEBUG_printf(" Returning new card object: %p", self); + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t sd_deinit(mp_obj_t self_in) { + sdcard_card_obj_t *self = self_in; + + DEBUG_printf("De-init host\n"); + + if (self->flags & SDCARD_CARD_FLAGS_HOST_INIT_DONE) { + self->host.deinit(); + self->flags &= ~SDCARD_CARD_FLAGS_HOST_INIT_DONE; + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(sd_deinit_obj, sd_deinit); + +STATIC mp_obj_t sd_info(mp_obj_t self_in) { + sdcard_card_obj_t *self = self_in; + // We could potential return a great deal more SD card data but it + // is not clear that it is worth the extra code space to do + // so. For the most part people only care about the card size and + // block size. + + check_esp_err(sdcard_ensure_card_init((sdcard_card_obj_t *) self, false)); + + uint32_t log_block_nbr = self->card.csd.capacity; + uint32_t log_block_size = _SECTOR_SIZE(self); + + mp_obj_t tuple[2] = { + mp_obj_new_int_from_ull((uint64_t)log_block_nbr * (uint64_t)log_block_size), + mp_obj_new_int_from_uint(log_block_size), + }; + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(sd_info_obj, sd_info); + +STATIC mp_obj_t machine_sdcard_readblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf) { + sdcard_card_obj_t *self = self_in; + mp_buffer_info_t bufinfo; + esp_err_t err; + + err = sdcard_ensure_card_init((sdcard_card_obj_t *) self, false); + if (err != ESP_OK) { + return false; + } + + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); + err = sdmmc_read_sectors(&(self->card), bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / _SECTOR_SIZE(self) ); + + return mp_obj_new_bool(err == ESP_OK); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_readblocks_obj, machine_sdcard_readblocks); + +STATIC mp_obj_t machine_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf) { + sdcard_card_obj_t *self = self_in; + mp_buffer_info_t bufinfo; + esp_err_t err; + + err = sdcard_ensure_card_init((sdcard_card_obj_t *) self, false); + if (err != ESP_OK) { + return false; + } + + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + err = sdmmc_write_sectors(&(self->card), bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / _SECTOR_SIZE(self) ); + + return mp_obj_new_bool(err == ESP_OK); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_writeblocks_obj, machine_sdcard_writeblocks); + +STATIC mp_obj_t machine_sdcard_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { + sdcard_card_obj_t *self = self_in; + esp_err_t err = ESP_OK; + mp_int_t cmd = mp_obj_get_int(cmd_in); + + switch (cmd) { + case BP_IOCTL_INIT: + err = sdcard_ensure_card_init(self, false); + return MP_OBJ_NEW_SMALL_INT((err == ESP_OK) ? 0 : -1); + + case BP_IOCTL_DEINIT: + // Ensure that future attempts to look at info re-read the card + self->flags &= ~SDCARD_CARD_FLAGS_CARD_INIT_DONE; + return MP_OBJ_NEW_SMALL_INT(0); // success + + case BP_IOCTL_SYNC: + // nothing to do + return MP_OBJ_NEW_SMALL_INT(0); // success + + case BP_IOCTL_SEC_COUNT: + err = sdcard_ensure_card_init(self, false); + if (err != ESP_OK) + return MP_OBJ_NEW_SMALL_INT(-1); + return MP_OBJ_NEW_SMALL_INT(self->card.csd.capacity); + + case BP_IOCTL_SEC_SIZE: + err = sdcard_ensure_card_init(self, false); + if (err != ESP_OK) + return MP_OBJ_NEW_SMALL_INT(-1); + return MP_OBJ_NEW_SMALL_INT(_SECTOR_SIZE(self)); + + default: // unknown command + return MP_OBJ_NEW_SMALL_INT(-1); // error + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_ioctl_obj, machine_sdcard_ioctl); + +STATIC const mp_rom_map_elem_t machine_sdcard_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&sd_info_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&sd_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sd_deinit_obj) }, + // block device protocol + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&machine_sdcard_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&machine_sdcard_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&machine_sdcard_ioctl_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(machine_sdcard_locals_dict, machine_sdcard_locals_dict_table); + +const mp_obj_type_t machine_sdcard_type = { + { &mp_type_type }, + .name = MP_QSTR_SDCard, + .make_new = machine_sdcard_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_sdcard_locals_dict, +}; + +#endif // MICROPY_HW_ENABLE_SDCARD diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index bc459ee5c29b2..fb864947d229d 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -235,6 +235,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, + #if MICROPY_HW_ENABLE_SDCARD + { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&machine_sdcard_type) }, + #endif // wake abilities { MP_ROM_QSTR(MP_QSTR_SLEEP), MP_ROM_INT(MACHINE_WAKE_SLEEP) }, diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index b65b427b4ea33..ca1776d8bf721 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -19,6 +19,7 @@ extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_hw_spi_type; extern const mp_obj_type_t machine_uart_type; extern const mp_obj_type_t machine_rtc_type; +extern const mp_obj_type_t machine_sdcard_type; void machine_pins_init(void); void machine_pins_deinit(void); diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 7b9b40025035a..bd19c6bfbdb2d 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -141,6 +141,7 @@ #define MICROPY_PY_MACHINE_SPI_MSB (0) #define MICROPY_PY_MACHINE_SPI_LSB (1) #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new +#define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly #define MICROPY_PY_USSL (1) From 6077d1715013dac50b54d8321a7a0f51db34aa5c Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Fri, 31 May 2019 01:04:32 -0600 Subject: [PATCH 0138/1299] docs/machine: Add initial docs for new machine.SDCard class. --- docs/library/machine.SD.rst | 4 +- docs/library/machine.SDCard.rst | 122 ++++++++++++++++++++++++++++++++ docs/library/machine.rst | 1 + 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 docs/library/machine.SDCard.rst diff --git a/docs/library/machine.SD.rst b/docs/library/machine.SD.rst index 9c58e73545edd..d985db231aa44 100644 --- a/docs/library/machine.SD.rst +++ b/docs/library/machine.SD.rst @@ -1,8 +1,8 @@ .. currentmodule:: machine .. _machine.SD: -class SD -- secure digital memory card -====================================== +class SD -- secure digital memory card (cc3200 port only) +========================================================= .. warning:: diff --git a/docs/library/machine.SDCard.rst b/docs/library/machine.SDCard.rst new file mode 100644 index 0000000000000..34bb2e48bf38d --- /dev/null +++ b/docs/library/machine.SDCard.rst @@ -0,0 +1,122 @@ +.. currentmodule:: machine +.. _machine.SDCard: + +class SDCard -- secure digital memory card +========================================== + +SD cards are one of the most common small form factor removable storage media. +SD cards come in a variety of sizes and phsyical form factors. MMC cards are +similar removable storage devices while eMMC devices are electically similar +storage devices designed to be embedded into other systems. All three form +share a common protocol for communication with their host system and high-level +support looks the same for them all. As such in MicroPython they are implemented +in a single class called :class:`machine.SDCard` . + +Both SD and MMC interfaces support being accessed with a variety of bus widths. +When being accessed with a 1-bit wide interface they can be accessed using the +SPI protocol. Different MicroPython hardware platforms support different widths +and pin configurations but for most platforms there is a standard configuation +for any given hardware. In general constructing an `SDCard`` object with without +passing any parameters will initialise the interface to the default card slot +for the current hardware. The arguments listed below represent the common +arguments that might need to be set in order to use either a non-stanard slot +or a non-standard pin assignment. The exact subset of arguments suported will +vary from platform to platform. + +.. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None) + + This class provides access to SD or MMC storage cards using either + a dedicated SD/MMC interface hardware or through an SPI channel. + The class implements the block protocol defined by :class:`uos.AbstractBlockDev`. + This allows the mounting of an SD card to be as simple as:: + + uos.mount(storage.SDCard(), "/sd") + + The constrcutor takes the following paramters: + + - *slot* selects which of the available interfaces to use. Leaving this + unset will select the default interface. + + - *width* selects the bus width for the SD/MMC interface. + + - *cd* can be used to specify a card-detect pin. + + - *wp* can be used to specify a write-protect pin. + + - *sck* can be used to specify an SPI clock pin. + + - *miso* can be used to specify an SPI miso pin. + + - *mosi* can be used to specify an SPI mosi pin. + + - *cs* can be used to specify an SPI chip select pin. + +Implementation-specific details +------------------------------- + +Different implementations of the ``SDCard`` class on different hardware support +varying subsets of the options above. + +PyBoard +``````` + +The standard PyBoard has just one slot. No arguments are necessary or supported. + +ESP32 +````` + +The ESP32 provides two channels of SD/MMC hardware and also supports +access to SD Cards through either of the two SPI ports that are +generally available to the user. As a result the *slot* argument can +take a value between 0 and 3, inclusive. Slots 0 and 1 use the +built-in SD/MMC hardware while slots 2 and 3 use the SPI ports. Slot 0 +supports 1, 4 or 8-bit wide access while slot 1 supports 1 or 4-bit +access; the SPI slots only support 1-bit access. + + .. note:: Slot 0 is used to communicate with on-board flash memory + on most ESP32 modules and so will be unavailable to the + user. + + .. note:: Most ESP32 modules that provide an SD card slot using the + dedicated hardware only wire up 1 data pin, so the default + value for *width* is 1. + +The pins used by the dedicated SD/MMC hardware are fixed. The pins +used by the SPI hardware can be reassigned. + + .. note:: If any of the SPI signals are remapped then all of the SPI + signals will pass through a GPIO multiplexer unit which + can limit the performance of high frequency signals. Since + the normal operating speed for SD cards is 40MHz this can + cause problems on some cards. + +The default (and preferred) pin assignment are as follows: + + ====== ====== ====== ====== ====== + Slot 0 1 2 3 + ------ ------ ------ ------ ------ + Signal Pin Pin Pin Pin + ====== ====== ====== ====== ====== + sck 6 14 18 14 + cmd 11 15 + cs 5 15 + miso 19 12 + mosi 23 13 + D0 7 2 + D1 8 4 + D2 9 12 + D3 10 13 + D4 16 + D5 17 + D6 5 + D7 18 + ====== ====== ====== ====== ====== + +cc3200 +`````` + +You can set the pins used for SPI access by passing a tuple as the +*pins* argument. + +*Note:* The current cc3200 SD card implementation names the this class +:class:`machine.SD` rather than :class:`machine.SDCard` . diff --git a/docs/library/machine.rst b/docs/library/machine.rst index a7b59577610be..8cc5efe593d4b 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -168,3 +168,4 @@ Classes machine.Timer.rst machine.WDT.rst machine.SD.rst + machine.SDCard.rst From 0a6c479187d0b50a92b65f639e377678bde8034e Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 May 2019 19:06:17 +1000 Subject: [PATCH 0139/1299] lib/cmsis: Upgrade to CMSIS 5.5.1. From https://github.com/ARM-software/CMSIS_5.git, tag 5.5.1 --- lib/cmsis/inc/cmsis_armcc.h | 247 +- lib/cmsis/inc/cmsis_armclang.h | 1420 ++++++++ ...{cmsis_armcc_V6.h => cmsis_armclang_ltm.h} | 974 +++--- lib/cmsis/inc/cmsis_compiler.h | 271 ++ lib/cmsis/inc/cmsis_gcc.h | 1164 +++++-- lib/cmsis/inc/cmsis_iccarm.h | 940 ++++++ lib/cmsis/inc/cmsis_version.h | 39 + lib/cmsis/inc/core_armv81mml.h | 2967 +++++++++++++++++ lib/cmsis/inc/core_armv8mbl.h | 1918 +++++++++++ lib/cmsis/inc/core_armv8mml.h | 2832 ++++++++++++++++ lib/cmsis/inc/core_cm0.h | 399 ++- lib/cmsis/inc/core_cm0plus.h | 424 ++- lib/cmsis/inc/core_cm1.h | 976 ++++++ lib/cmsis/inc/core_cm23.h | 1993 +++++++++++ lib/cmsis/inc/core_cm3.h | 519 ++- lib/cmsis/inc/core_cm33.h | 2907 ++++++++++++++++ lib/cmsis/inc/core_cm35p.h | 2907 ++++++++++++++++ lib/cmsis/inc/core_cm4.h | 560 ++-- lib/cmsis/inc/core_cm7.h | 719 ++-- lib/cmsis/inc/core_cmFunc.h | 87 - lib/cmsis/inc/core_cmInstr.h | 87 - lib/cmsis/inc/core_cmSimd.h | 96 - lib/cmsis/inc/core_sc000.h | 346 +- lib/cmsis/inc/core_sc300.h | 468 ++- lib/cmsis/inc/mpu_armv7.h | 272 ++ lib/cmsis/inc/mpu_armv8.h | 346 ++ lib/cmsis/inc/tz_context.h | 70 + 27 files changed, 23792 insertions(+), 2156 deletions(-) create mode 100644 lib/cmsis/inc/cmsis_armclang.h rename lib/cmsis/inc/{cmsis_armcc_V6.h => cmsis_armclang_ltm.h} (56%) create mode 100644 lib/cmsis/inc/cmsis_compiler.h create mode 100644 lib/cmsis/inc/cmsis_iccarm.h create mode 100644 lib/cmsis/inc/cmsis_version.h create mode 100644 lib/cmsis/inc/core_armv81mml.h create mode 100644 lib/cmsis/inc/core_armv8mbl.h create mode 100644 lib/cmsis/inc/core_armv8mml.h create mode 100644 lib/cmsis/inc/core_cm1.h create mode 100644 lib/cmsis/inc/core_cm23.h create mode 100644 lib/cmsis/inc/core_cm33.h create mode 100644 lib/cmsis/inc/core_cm35p.h delete mode 100644 lib/cmsis/inc/core_cmFunc.h delete mode 100644 lib/cmsis/inc/core_cmInstr.h delete mode 100644 lib/cmsis/inc/core_cmSimd.h create mode 100644 lib/cmsis/inc/mpu_armv7.h create mode 100644 lib/cmsis/inc/mpu_armv8.h create mode 100644 lib/cmsis/inc/tz_context.h diff --git a/lib/cmsis/inc/cmsis_armcc.h b/lib/cmsis/inc/cmsis_armcc.h index 74c49c67defb6..174d744033029 100644 --- a/lib/cmsis/inc/cmsis_armcc.h +++ b/lib/cmsis/inc/cmsis_armcc.h @@ -1,43 +1,108 @@ /**************************************************************************//** * @file cmsis_armcc.h - * @brief CMSIS Cortex-M Core Function/Instruction Header File - * @version V4.30 - * @date 20. October 2015 + * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file + * @version V5.0.5 + * @date 14. December 2018 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __CMSIS_ARMCC_H #define __CMSIS_ARMCC_H #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) - #error "Please use ARM Compiler Toolchain V4.0.677 or later!" + #error "Please use Arm Compiler Toolchain V4.0.677 or later!" +#endif + +/* CMSIS compiler control architecture macros */ +#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ + (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) + #define __ARM_ARCH_6M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) + #define __ARM_ARCH_7M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) + #define __ARM_ARCH_7EM__ 1 +#endif + + /* __ARM_ARCH_8M_BASE__ not applicable */ + /* __ARM_ARCH_8M_MAIN__ not applicable */ + +/* CMSIS compiler control DSP macros */ +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __ARM_FEATURE_DSP 1 +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE static __forceinline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __declspec(noreturn) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed)) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT __packed struct +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION __packed union +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict #endif /* ########################### Core Function Access ########################### */ @@ -46,7 +111,19 @@ @{ */ +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ /* intrinsic void __enable_irq(); */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ /* intrinsic void __disable_irq(); */ /** @@ -181,7 +258,8 @@ __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) } -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) /** \brief Enable FIQ @@ -256,13 +334,12 @@ __STATIC_INLINE uint32_t __get_FAULTMASK(void) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) { register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & (uint32_t)1); + __regFaultMask = (faultMask & (uint32_t)1U); } -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ - +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ -#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) /** \brief Get FPSCR @@ -271,7 +348,8 @@ __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) */ __STATIC_INLINE uint32_t __get_FPSCR(void) { -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) register uint32_t __regfpscr __ASM("fpscr"); return(__regfpscr); #else @@ -287,15 +365,15 @@ __STATIC_INLINE uint32_t __get_FPSCR(void) */ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) { -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) register uint32_t __regfpscr __ASM("fpscr"); __regfpscr = (fpscr); +#else + (void)fpscr; #endif } -#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ - - /*@} end of CMSIS_Core_RegAccFunctions */ @@ -369,9 +447,10 @@ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) __schedule_barrier();\ } while (0U) + /** \brief Reverse byte order (32 bit) - \details Reverses the byte order in integer value. + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. \param [in] value Value to reverse \return Reversed value */ @@ -380,7 +459,7 @@ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) /** \brief Reverse byte order (16 bit) - \details Reverses the byte order in two unsigned short values. + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. \param [in] value Value to reverse \return Reversed value */ @@ -392,14 +471,15 @@ __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(u } #endif + /** - \brief Reverse byte order in signed short value - \details Reverses the byte order in a signed short value with sign extension to integer. + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. \param [in] value Value to reverse \return Reversed value */ #ifndef __NO_EMBEDDED_ASM -__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) { revsh r0, r0 bx lr @@ -410,8 +490,8 @@ __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(in /** \brief Rotate Right in unsigned value (32 bit) \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate \return Rotated value */ #define __ROR __ror @@ -433,23 +513,24 @@ __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(in \param [in] value Value to reverse \return Reversed value */ -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) #define __RBIT __rbit #else __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) { uint32_t result; - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) + for (value >>= 1U; value != 0U; value >>= 1U) { result <<= 1U; result |= value & 1U; s--; } result <<= s; /* shift when v's highest bits are zero */ - return(result); + return result; } #endif @@ -463,7 +544,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) #define __CLZ __clz -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) /** \brief LDR Exclusive (8 bit) @@ -645,7 +727,60 @@ __attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint3 */ #define __STRT(value, ptr) __strt(value, ptr) -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ @@ -656,7 +791,7 @@ __attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint3 @{ */ -#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) #define __SADD8 __sadd8 #define __QADD8 __qadd8 @@ -727,7 +862,7 @@ __attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint3 #define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ ((int64_t)(ARG3) << 32U) ) >> 32U)) -#endif /* (__CORTEX_M >= 0x04) */ +#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ /*@} end of group CMSIS_SIMD_intrinsics */ diff --git a/lib/cmsis/inc/cmsis_armclang.h b/lib/cmsis/inc/cmsis_armclang.h new file mode 100644 index 0000000000000..6a8867d57417e --- /dev/null +++ b/lib/cmsis/inc/cmsis_armclang.h @@ -0,0 +1,1420 @@ +/**************************************************************************//** + * @file cmsis_armclang.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V5.1.0 + * @date 14. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +#ifndef __ARM_COMPAT_H +#include /* Compatibility header for Arm Compiler 5 intrinsics */ +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); see arm_compat.h */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); see arm_compat.h */ + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq /* see arm_compat.h */ + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq /* see arm_compat.h */ + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +#define __SADD8 __builtin_arm_sadd8 +#define __QADD8 __builtin_arm_qadd8 +#define __SHADD8 __builtin_arm_shadd8 +#define __UADD8 __builtin_arm_uadd8 +#define __UQADD8 __builtin_arm_uqadd8 +#define __UHADD8 __builtin_arm_uhadd8 +#define __SSUB8 __builtin_arm_ssub8 +#define __QSUB8 __builtin_arm_qsub8 +#define __SHSUB8 __builtin_arm_shsub8 +#define __USUB8 __builtin_arm_usub8 +#define __UQSUB8 __builtin_arm_uqsub8 +#define __UHSUB8 __builtin_arm_uhsub8 +#define __SADD16 __builtin_arm_sadd16 +#define __QADD16 __builtin_arm_qadd16 +#define __SHADD16 __builtin_arm_shadd16 +#define __UADD16 __builtin_arm_uadd16 +#define __UQADD16 __builtin_arm_uqadd16 +#define __UHADD16 __builtin_arm_uhadd16 +#define __SSUB16 __builtin_arm_ssub16 +#define __QSUB16 __builtin_arm_qsub16 +#define __SHSUB16 __builtin_arm_shsub16 +#define __USUB16 __builtin_arm_usub16 +#define __UQSUB16 __builtin_arm_uqsub16 +#define __UHSUB16 __builtin_arm_uhsub16 +#define __SASX __builtin_arm_sasx +#define __QASX __builtin_arm_qasx +#define __SHASX __builtin_arm_shasx +#define __UASX __builtin_arm_uasx +#define __UQASX __builtin_arm_uqasx +#define __UHASX __builtin_arm_uhasx +#define __SSAX __builtin_arm_ssax +#define __QSAX __builtin_arm_qsax +#define __SHSAX __builtin_arm_shsax +#define __USAX __builtin_arm_usax +#define __UQSAX __builtin_arm_uqsax +#define __UHSAX __builtin_arm_uhsax +#define __USAD8 __builtin_arm_usad8 +#define __USADA8 __builtin_arm_usada8 +#define __SSAT16 __builtin_arm_ssat16 +#define __USAT16 __builtin_arm_usat16 +#define __UXTB16 __builtin_arm_uxtb16 +#define __UXTAB16 __builtin_arm_uxtab16 +#define __SXTB16 __builtin_arm_sxtb16 +#define __SXTAB16 __builtin_arm_sxtab16 +#define __SMUAD __builtin_arm_smuad +#define __SMUADX __builtin_arm_smuadx +#define __SMLAD __builtin_arm_smlad +#define __SMLADX __builtin_arm_smladx +#define __SMLALD __builtin_arm_smlald +#define __SMLALDX __builtin_arm_smlaldx +#define __SMUSD __builtin_arm_smusd +#define __SMUSDX __builtin_arm_smusdx +#define __SMLSD __builtin_arm_smlsd +#define __SMLSDX __builtin_arm_smlsdx +#define __SMLSLD __builtin_arm_smlsld +#define __SMLSLDX __builtin_arm_smlsldx +#define __SEL __builtin_arm_sel +#define __QADD __builtin_arm_qadd +#define __QSUB __builtin_arm_qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/lib/cmsis/inc/cmsis_armcc_V6.h b/lib/cmsis/inc/cmsis_armclang_ltm.h similarity index 56% rename from lib/cmsis/inc/cmsis_armcc_V6.h rename to lib/cmsis/inc/cmsis_armclang_ltm.h index cd13240ce3602..e4002a3fc4c93 100644 --- a/lib/cmsis/inc/cmsis_armcc_V6.h +++ b/lib/cmsis/inc/cmsis_armclang_ltm.h @@ -1,39 +1,115 @@ /**************************************************************************//** - * @file cmsis_armcc_V6.h - * @brief CMSIS Cortex-M Core Function/Instruction Header File - * @version V4.30 - * @date 20. October 2015 + * @file cmsis_armclang_ltm.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V1.0.1 + * @date 19. March 2019 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#ifndef __CMSIS_ARMCC_V6_H -#define __CMSIS_ARMCC_V6_H +/* + * Copyright (c) 2018-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +#ifndef __ARM_COMPAT_H +#include /* Compatibility header for Arm Compiler 5 intrinsics */ +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif /* ########################### Core Function Access ########################### */ @@ -47,10 +123,7 @@ \details Enables IRQ interrupts by clearing the I-bit in the CPSR. Can only be executed in Privileged modes. */ -__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) -{ - __ASM volatile ("cpsie i" : : : "memory"); -} +/* intrinsic void __enable_irq(); see arm_compat.h */ /** @@ -58,10 +131,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) \details Disables IRQ interrupts by setting the I-bit in the CPSR. Can only be executed in Privileged modes. */ -__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) -{ - __ASM volatile ("cpsid i" : : : "memory"); -} +/* intrinsic void __disable_irq(); see arm_compat.h */ /** @@ -69,7 +139,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) \details Returns the content of the Control Register. \return Control Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) { uint32_t result; @@ -78,13 +148,13 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Control Register (non-secure) \details Returns the content of the non-secure Control Register when in secure mode. \return non-secure Control Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) { uint32_t result; @@ -99,19 +169,19 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void \details Writes the given value to the Control Register. \param [in] control Control Register value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) { __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Control Register (non-secure) \details Writes the given value to the non-secure Control Register when in secure state. \param [in] control Control Register value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) { __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); } @@ -123,7 +193,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t \details Returns the content of the IPSR Register. \return IPSR Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) { uint32_t result; @@ -132,28 +202,12 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) } -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get IPSR Register (non-secure) - \details Returns the content of the non-secure IPSR Register when in secure state. - \return IPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) ); - return(result); -} -#endif - - /** \brief Get APSR Register \details Returns the content of the APSR Register. \return APSR Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) +__STATIC_FORCEINLINE uint32_t __get_APSR(void) { uint32_t result; @@ -162,28 +216,12 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) } -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get APSR Register (non-secure) - \details Returns the content of the non-secure APSR Register when in secure state. - \return APSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) ); - return(result); -} -#endif - - /** \brief Get xPSR Register \details Returns the content of the xPSR Register. \return xPSR Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) { uint32_t result; @@ -192,45 +230,29 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) } -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get xPSR Register (non-secure) - \details Returns the content of the non-secure xPSR Register when in secure state. - \return xPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) ); - return(result); -} -#endif - - /** \brief Get Process Stack Pointer \details Returns the current value of the Process Stack Pointer (PSP). \return PSP Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) +__STATIC_FORCEINLINE uint32_t __get_PSP(void) { - register uint32_t result; + uint32_t result; __ASM volatile ("MRS %0, psp" : "=r" (result) ); return(result); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer (non-secure) \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. \return PSP Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) { - register uint32_t result; + uint32_t result; __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); return(result); @@ -243,21 +265,21 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) \details Assigns the given value to the Process Stack Pointer (PSP). \param [in] topOfProcStack Process Stack Pointer value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) { - __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp"); + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. \param [in] topOfProcStack Process Stack Pointer value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { - __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp"); + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } #endif @@ -267,24 +289,24 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t top \details Returns the current value of the Main Stack Pointer (MSP). \return MSP Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) +__STATIC_FORCEINLINE uint32_t __get_MSP(void) { - register uint32_t result; + uint32_t result; __ASM volatile ("MRS %0, msp" : "=r" (result) ); return(result); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer (non-secure) \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. \return MSP Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) { - register uint32_t result; + uint32_t result; __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); return(result); @@ -297,21 +319,48 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) \details Assigns the given value to the Main Stack Pointer (MSP). \param [in] topOfMainStack Main Stack Pointer value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) { - __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp"); + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer (non-secure) \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. \param [in] topOfMainStack Main Stack Pointer value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) { - __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp"); + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); } #endif @@ -321,7 +370,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t top \details Returns the current state of the priority mask bit from the Priority Mask Register. \return Priority Mask value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) { uint32_t result; @@ -330,13 +379,13 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Priority Mask (non-secure) \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. \return Priority Mask value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) { uint32_t result; @@ -351,36 +400,34 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void \details Assigns the given value to the Priority Mask Register. \param [in] priMask Priority Mask */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) { __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Priority Mask (non-secure) \details Assigns the given value to the non-secure Priority Mask Register when in secure state. \param [in] priMask Priority Mask */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) { __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); } #endif -#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ - +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Enable FIQ \details Enables FIQ interrupts by clearing the F-bit in the CPSR. Can only be executed in Privileged modes. */ -__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) -{ - __ASM volatile ("cpsie f" : : : "memory"); -} +#define __enable_fault_irq __enable_fiq /* see arm_compat.h */ /** @@ -388,10 +435,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) \details Disables FIQ interrupts by setting the F-bit in the CPSR. Can only be executed in Privileged modes. */ -__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) -{ - __ASM volatile ("cpsid f" : : : "memory"); -} +#define __disable_fault_irq __disable_fiq /* see arm_compat.h */ /** @@ -399,7 +443,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) \details Returns the current value of the Base Priority register. \return Base Priority register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; @@ -408,13 +452,13 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Base Priority (non-secure) \details Returns the current value of the non-secure Base Priority register when in secure state. \return Base Priority register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) { uint32_t result; @@ -429,21 +473,21 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void \details Assigns the given value to the Base Priority register. \param [in] basePri Base Priority value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { - __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Base Priority (non-secure) \details Assigns the given value to the non-secure Base Priority register when in secure state. \param [in] basePri Base Priority value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) { - __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory"); + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); } #endif @@ -454,32 +498,18 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { - __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set Base Priority with condition (non_secure) - \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) -{ - __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory"); -} -#endif - - /** \brief Get Fault Mask \details Returns the current value of the Fault Mask register. \return Fault Mask register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { uint32_t result; @@ -488,13 +518,13 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Fault Mask (non-secure) \details Returns the current value of the non-secure Fault Mask register when in secure state. \return Fault Mask register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) { uint32_t result; @@ -509,223 +539,233 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(vo \details Assigns the given value to the Fault Mask register. \param [in] faultMask Fault Mask value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } -#if (__ARM_FEATURE_CMSE == 3U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Fault Mask (non-secure) \details Assigns the given value to the non-secure Fault Mask register when in secure state. \param [in] faultMask Fault Mask value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) { __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); } #endif +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ -#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ - -#if (__ARM_ARCH_8M__ == 1U) +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). \return PSPLIM Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) { - register uint32_t result; - +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; __ASM volatile ("MRS %0, psplim" : "=r" (result) ); - return(result); + return result; +#endif } - -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \return PSPLIM Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) { - register uint32_t result; - +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); - return(result); + return result; +#endif } #endif /** \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) { +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif } -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) { +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif } #endif /** \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). \return MSPLIM Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) { - register uint32_t result; - +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; __ASM volatile ("MRS %0, msplim" : "=r" (result) ); - - return(result); + return result; +#endif } -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. \return MSPLIM Register value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) { - register uint32_t result; - +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); - return(result); + return result; +#endif } #endif /** \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) { +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif } -#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) /** \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. \param [in] MainStackPtrLimit Main Stack Pointer value to set */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) { +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif } #endif -#endif /* (__ARM_ARCH_8M__ == 1U) */ - - -#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */ +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /** \brief Get FPSCR - \details eturns the current value of the Floating Point Status/Control register. + \details Returns the current value of the Floating Point Status/Control register. \return Floating Point Status/Control register value */ -#define __get_FPSCR __builtin_arm_get_fpscr -#if 0 -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - uint32_t result; - - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); - __ASM volatile (""); - return(result); +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr #else - return(0); -#endif -} +#define __get_FPSCR() ((uint32_t)0U) #endif -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Get FPSCR (non-secure) - \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state. - \return Floating Point Status/Control register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - uint32_t result; - - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) ); - __ASM volatile (""); - return(result); -#else - return(0); -#endif -} -#endif - - /** \brief Set FPSCR \details Assigns the given value to the Floating Point Status/Control register. \param [in] fpscr Floating Point Status/Control value to set */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) #define __set_FPSCR __builtin_arm_set_fpscr -#if 0 -__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); -#endif -} -#endif - -#if (__ARM_FEATURE_CMSE == 3U) -/** - \brief Set FPSCR (non-secure) - \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state. - \param [in] fpscr Floating Point Status/Control value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ - __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); -#endif -} +#else +#define __set_FPSCR(x) ((void)(x)) #endif -#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ - - /*@} end of CMSIS_Core_RegAccFunctions */ @@ -781,14 +821,14 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t f so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. */ -#define __ISB() __builtin_arm_isb(0xF); +#define __ISB() __builtin_arm_isb(0xF) /** \brief Data Synchronization Barrier \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ -#define __DSB() __builtin_arm_dsb(0xF); +#define __DSB() __builtin_arm_dsb(0xF) /** @@ -796,50 +836,34 @@ __attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t f \details Ensures the apparent order of the explicit memory operations before and after the instruction, without ensuring their completion. */ -#define __DMB() __builtin_arm_dmb(0xF); +#define __DMB() __builtin_arm_dmb(0xF) /** \brief Reverse byte order (32 bit) - \details Reverses the byte order in integer value. + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. \param [in] value Value to reverse \return Reversed value */ -#define __REV __builtin_bswap32 +#define __REV(value) __builtin_bswap32(value) /** \brief Reverse byte order (16 bit) - \details Reverses the byte order in two unsigned short values. + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. \param [in] value Value to reverse \return Reversed value */ -#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ -#if 0 -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} -#endif +#define __REV16(value) __ROR(__REV(value), 16) /** - \brief Reverse byte order in signed short value - \details Reverses the byte order in a signed short value with sign extension to integer. + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. \param [in] value Value to reverse \return Reversed value */ - /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ -__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) -{ - int32_t result; - - __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} +#define __REVSH(value) (int16_t)__builtin_bswap16(value) /** @@ -849,8 +873,13 @@ __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) \param [in] op2 Number of Bits to rotate \return Rotated value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } return (op1 >> op2) | (op1 << (32U - op2)); } @@ -858,11 +887,11 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint /** \brief Breakpoint \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) +#define __BKPT(value) __ASM volatile ("bkpt "#value) /** @@ -871,28 +900,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint \param [in] value Value to reverse \return Reversed value */ - /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - -#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ - __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); -#else - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ - - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ -#endif - return(result); -} - +#define __RBIT __builtin_arm_rbit /** \brief Count leading zeros @@ -900,11 +908,29 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) \param [in] value Value to count the leading zeros \return number of leading zeros in value */ -#define __CLZ __builtin_clz - +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} -#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief LDR Exclusive (8 bit) \details Executes a exclusive LDR instruction for 8 bit value. @@ -971,6 +997,15 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) */ #define __CLREX __builtin_arm_clrex +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Signed Saturate @@ -979,13 +1014,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) \param [in] sat Bit position to saturate to (1..32) \return Saturated value */ -/*#define __SSAT __builtin_arm_ssat*/ -#define __SSAT(ARG1,ARG2) \ -({ \ - int32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) +#define __SSAT __builtin_arm_ssat /** @@ -996,14 +1025,6 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) \return Saturated value */ #define __USAT __builtin_arm_usat -#if 0 -#define __USAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) -#endif /** @@ -1013,7 +1034,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) \param [in] value Value to rotate \return Rotated value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; @@ -1028,12 +1049,12 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { - uint32_t result; + uint32_t result; - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); /* Add explicit type cast here */ + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ } @@ -1043,12 +1064,12 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { - uint32_t result; + uint32_t result; - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); /* Add explicit type cast here */ + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ } @@ -1058,12 +1079,12 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_ \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { - uint32_t result; + uint32_t result; - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); } @@ -1073,9 +1094,9 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } @@ -1085,9 +1106,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volat \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { - __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } @@ -1097,28 +1118,83 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, vola \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) { - __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; } -#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ -#if (__ARM_ARCH_8M__ == 1U) +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief Load-Acquire (8 bit) \details Executes a LDAB instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t *ptr) +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) { - uint32_t result; + uint32_t result; - __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); } @@ -1128,12 +1204,12 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t * \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t *ptr) +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) { - uint32_t result; + uint32_t result; - __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); } @@ -1143,12 +1219,12 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t *ptr) +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) { - uint32_t result; + uint32_t result; - __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); } @@ -1158,9 +1234,9 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } @@ -1170,9 +1246,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volati \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) { - __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } @@ -1182,9 +1258,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volat \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) { - __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } @@ -1247,7 +1323,8 @@ __attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volati */ #define __STLEX (uint32_t)__builtin_arm_stlex -#endif /* (__ARM_ARCH_8M__ == 1U) */ +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ @@ -1258,9 +1335,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volati @{ */ -#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */ +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1268,7 +1345,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1276,7 +1353,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1284,7 +1361,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1292,7 +1369,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1300,7 +1377,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1309,7 +1386,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, u } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1317,7 +1394,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1325,7 +1402,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1333,7 +1410,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1341,7 +1418,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1349,7 +1426,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1358,7 +1435,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, u } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1366,7 +1443,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1374,7 +1451,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1382,7 +1459,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1390,7 +1467,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1398,7 +1475,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1406,7 +1483,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1414,7 +1491,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1422,7 +1499,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1430,7 +1507,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1438,7 +1515,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1446,7 +1523,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1454,7 +1531,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1462,7 +1539,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uin return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1470,7 +1547,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uin return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1478,7 +1555,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1486,7 +1563,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uin return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1494,7 +1571,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1502,7 +1579,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1510,7 +1587,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uin return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1518,7 +1595,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uin return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1526,7 +1603,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1534,7 +1611,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uin return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1542,7 +1619,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1550,7 +1627,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1558,7 +1635,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1568,7 +1645,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, u #define __SSAT16(ARG1,ARG2) \ ({ \ - uint32_t __RES, __ARG1 = (ARG1); \ + int32_t __RES, __ARG1 = (ARG1); \ __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) @@ -1580,7 +1657,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, u __RES; \ }) -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) { uint32_t result; @@ -1588,7 +1665,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1596,7 +1673,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) { uint32_t result; @@ -1604,7 +1681,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1612,7 +1689,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1620,7 +1697,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1628,7 +1705,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1636,7 +1713,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1644,7 +1721,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1661,7 +1738,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, return(llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1678,7 +1755,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, return(llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1686,7 +1763,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1694,7 +1771,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1702,7 +1779,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, u return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1710,7 +1787,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, return(result); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1727,7 +1804,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, return(llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1744,7 +1821,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, return(llr.w64); } -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1752,7 +1829,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, ui return(result); } -__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) { int32_t result; @@ -1760,7 +1837,7 @@ __attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, in return(result); } -__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) { int32_t result; @@ -1768,33 +1845,22 @@ __attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, in return(result); } -#define __PKHBT(ARG1,ARG2,ARG3) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ - __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ - __RES; \ - }) +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) -#define __PKHTB(ARG1,ARG2,ARG3) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ - if (ARG3 == 0) \ - __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ - else \ - __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ - __RES; \ - }) +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) -__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { - int32_t result; + int32_t result; - __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); - return(result); + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); } -#endif /* (__ARM_FEATURE_DSP == 1U) */ +#endif /* (__ARM_FEATURE_DSP == 1) */ /*@} end of group CMSIS_SIMD_intrinsics */ -#endif /* __CMSIS_ARMCC_V6_H */ +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/lib/cmsis/inc/cmsis_compiler.h b/lib/cmsis/inc/cmsis_compiler.h new file mode 100644 index 0000000000000..fdb1a971c6a8c --- /dev/null +++ b/lib/cmsis/inc/cmsis_compiler.h @@ -0,0 +1,271 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.1.0 + * @date 09. October 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_COMPILER_H +#define __CMSIS_COMPILER_H + +#include + +/* + * Arm Compiler 4/5 + */ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + + +/* + * Arm Compiler 6.6 LTM (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) + #include "cmsis_armclang_ltm.h" + + /* + * Arm Compiler above 6.10.1 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) + #include "cmsis_armclang.h" + + +/* + * GNU Compiler + */ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + + +/* + * IAR Compiler + */ +#elif defined ( __ICCARM__ ) + #include + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __attribute__((packed)) + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed)) + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) + #endif + #ifndef __RESTRICT + #define __RESTRICT __restrict + #endif + + +/* + * TASKING Compiler + */ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __packed__ + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __packed__ + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __packed__ T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __align(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + + +/* + * COSMIC Compiler + */ +#elif defined ( __CSMC__ ) + #include + + #ifndef __ASM + #define __ASM _asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + // NO RETURN is automatically detected hence no warning here + #define __NO_RETURN + #endif + #ifndef __USED + #warning No compiler specific solution for __USED. __USED is ignored. + #define __USED + #endif + #ifndef __WEAK + #define __WEAK __weak + #endif + #ifndef __PACKED + #define __PACKED @packed + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT @packed struct + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + @packed struct T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. + #define __ALIGNED(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + diff --git a/lib/cmsis/inc/cmsis_gcc.h b/lib/cmsis/inc/cmsis_gcc.h index bb89fbba9e400..d86b0a2d5a6d3 100644 --- a/lib/cmsis/inc/cmsis_gcc.h +++ b/lib/cmsis/inc/cmsis_gcc.h @@ -1,46 +1,117 @@ /**************************************************************************//** * @file cmsis_gcc.h - * @brief CMSIS Cortex-M Core Function/Instruction Header File - * @version V4.30 - * @date 20. October 2015 + * @brief CMSIS compiler GCC header file + * @version V5.1.0 + * @date 20. December 2018 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __CMSIS_GCC_H #define __CMSIS_GCC_H /* ignore some GCC warnings */ -#if defined ( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict #endif @@ -55,7 +126,7 @@ \details Enables IRQ interrupts by clearing the I-bit in the CPSR. Can only be executed in Privileged modes. */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +__STATIC_FORCEINLINE void __enable_irq(void) { __ASM volatile ("cpsie i" : : : "memory"); } @@ -64,9 +135,9 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) /** \brief Disable IRQ Interrupts \details Disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. + Can only be executed in Privileged modes. */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +__STATIC_FORCEINLINE void __disable_irq(void) { __ASM volatile ("cpsid i" : : : "memory"); } @@ -77,7 +148,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) \details Returns the content of the Control Register. \return Control Register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) { uint32_t result; @@ -86,23 +157,52 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + /** \brief Set Control Register \details Writes the given value to the Control Register. \param [in] control Control Register value to set */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) { __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + /** \brief Get IPSR Register \details Returns the content of the IPSR Register. \return IPSR Register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) { uint32_t result; @@ -116,7 +216,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) \details Returns the content of the APSR Register. \return APSR Register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +__STATIC_FORCEINLINE uint32_t __get_APSR(void) { uint32_t result; @@ -128,10 +228,9 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) /** \brief Get xPSR Register \details Returns the content of the xPSR Register. - - \return xPSR Register value + \return xPSR Register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) { uint32_t result; @@ -145,24 +244,53 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) \details Returns the current value of the Process Stack Pointer (PSP). \return PSP Register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +__STATIC_FORCEINLINE uint32_t __get_PSP(void) { - register uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + __ASM volatile ("MRS %0, psp" : "=r" (result) ); return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + /** \brief Set Process Stack Pointer \details Assigns the given value to the Process Stack Pointer (PSP). \param [in] topOfProcStack Process Stack Pointer value to set */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) { - __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); } +#endif /** @@ -170,25 +298,80 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOf \details Returns the current value of the Main Stack Pointer (MSP). \return MSP Register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +__STATIC_FORCEINLINE uint32_t __get_MSP(void) { - register uint32_t result; + uint32_t result; - __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + __ASM volatile ("MRS %0, msp" : "=r" (result) ); return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + /** \brief Set Main Stack Pointer \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + - \param [in] topOfMainStack Main Stack Pointer value to set +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) { - __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); } +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif /** @@ -196,34 +379,64 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOf \details Returns the current state of the priority mask bit from the Priority Mask Register. \return Priority Mask value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) { uint32_t result; - __ASM volatile ("MRS %0, primask" : "=r" (result) ); + __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); return(result); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); + return(result); +} +#endif + + /** \brief Set Priority Mask \details Assigns the given value to the Priority Mask Register. \param [in] priMask Priority Mask */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) { __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); } -#if (__CORTEX_M >= 0x03U) +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Enable FIQ \details Enables FIQ interrupts by clearing the F-bit in the CPSR. Can only be executed in Privileged modes. */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +__STATIC_FORCEINLINE void __enable_fault_irq(void) { __ASM volatile ("cpsie f" : : : "memory"); } @@ -234,7 +447,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) \details Disables FIQ interrupts by setting the F-bit in the CPSR. Can only be executed in Privileged modes. */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +__STATIC_FORCEINLINE void __disable_fault_irq(void) { __ASM volatile ("cpsid f" : : : "memory"); } @@ -245,7 +458,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void \details Returns the current value of the Base Priority register. \return Base Priority register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) { uint32_t result; @@ -254,26 +467,55 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + /** \brief Set Base Priority \details Assigns the given value to the Base Priority register. \param [in] basePri Base Priority value to set */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { - __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + /** \brief Set Base Priority with condition \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, or the new value increases the BASEPRI priority level. \param [in] basePri Base Priority value to set */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) { - __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); } @@ -282,7 +524,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32 \details Returns the current value of the Fault Mask register. \return Fault Mask register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) { uint32_t result; @@ -291,38 +533,253 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void } +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + /** \brief Set Fault Mask \details Assigns the given value to the Fault Mask register. \param [in] faultMask Fault Mask value to set */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) { __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); } -#endif /* (__CORTEX_M >= 0x03U) */ + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ -#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + /** \brief Get FPSCR \details Returns the current value of the Floating Point Status/Control register. \return Floating Point Status/Control register value */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else uint32_t result; - /* Empty asm statement works as a scheduling barrier */ - __ASM volatile (""); __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); - __ASM volatile (""); return(result); +#endif #else - return(0); + return(0U); #endif } @@ -332,19 +789,23 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) \details Assigns the given value to the Floating Point Status/Control register. \param [in] fpscr Floating Point Status/Control value to set */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - /* Empty asm statement works as a scheduling barrier */ - __ASM volatile (""); - __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); - __ASM volatile (""); +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; #endif } -#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ - - /*@} end of CMSIS_Core_RegAccFunctions */ @@ -360,9 +821,11 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fps * Otherwise, use general registers, specified by constraint "r" */ #if defined (__thumb__) && !defined (__thumb2__) #define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) #define __CMSIS_GCC_USE_REG(r) "l" (r) #else #define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) #define __CMSIS_GCC_USE_REG(r) "r" (r) #endif @@ -370,41 +833,28 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fps \brief No Operation \details No Operation does nothing. This instruction can be used for code alignment purposes. */ -__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) -{ - __ASM volatile ("nop"); -} - +#define __NOP() __ASM volatile ("nop") /** \brief Wait For Interrupt \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. */ -__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) -{ - __ASM volatile ("wfi"); -} +#define __WFI() __ASM volatile ("wfi") /** \brief Wait For Event \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. + a low-power state until one of a number of events occurs. */ -__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) -{ - __ASM volatile ("wfe"); -} +#define __WFE() __ASM volatile ("wfe") /** \brief Send Event \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. */ -__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) -{ - __ASM volatile ("sev"); -} +#define __SEV() __ASM volatile ("sev") /** @@ -413,7 +863,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __SEV(void) so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. */ -__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) +__STATIC_FORCEINLINE void __ISB(void) { __ASM volatile ("isb 0xF":::"memory"); } @@ -424,7 +874,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __ISB(void) \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ -__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) +__STATIC_FORCEINLINE void __DSB(void) { __ASM volatile ("dsb 0xF":::"memory"); } @@ -435,7 +885,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __DSB(void) \details Ensures the apparent order of the explicit memory operations before and after the instruction, without ensuring their completion. */ -__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) +__STATIC_FORCEINLINE void __DMB(void) { __ASM volatile ("dmb 0xF":::"memory"); } @@ -443,11 +893,11 @@ __attribute__((always_inline)) __STATIC_INLINE void __DMB(void) /** \brief Reverse byte order (32 bit) - \details Reverses the byte order in integer value. + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. \param [in] value Value to reverse \return Reversed value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) { #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) return __builtin_bswap32(value); @@ -455,41 +905,41 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) uint32_t result; __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); + return result; #endif } /** \brief Reverse byte order (16 bit) - \details Reverses the byte order in two unsigned short values. + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. \param [in] value Value to reverse \return Reversed value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) { uint32_t result; __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); + return result; } /** - \brief Reverse byte order in signed short value - \details Reverses the byte order in a signed short value with sign extension to integer. + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. \param [in] value Value to reverse \return Reversed value */ -__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) { #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - return (short)__builtin_bswap16(value); + return (int16_t)__builtin_bswap16(value); #else - int32_t result; + int16_t result; __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); + return result; #endif } @@ -497,12 +947,17 @@ __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) /** \brief Rotate Right in unsigned value (32 bit) \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate \return Rotated value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) { + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } return (op1 >> op2) | (op1 << (32U - op2)); } @@ -523,17 +978,19 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint \param [in] value Value to reverse \return Reversed value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) { uint32_t result; -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); #else - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) + for (value >>= 1U; value != 0U; value >>= 1U) { result <<= 1U; result |= value & 1U; @@ -541,7 +998,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) } result <<= s; /* shift when v's highest bits are zero */ #endif - return(result); + return result; } @@ -551,18 +1008,36 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) \param [in] value Value to count the leading zeros \return number of leading zeros in value */ -#define __CLZ __builtin_clz - +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) /** \brief LDR Exclusive (8 bit) \details Executes a exclusive LDR instruction for 8 bit value. \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) { uint32_t result; @@ -584,7 +1059,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) { uint32_t result; @@ -606,7 +1081,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16 \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) { uint32_t result; @@ -623,7 +1098,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32 \return 0 Function succeeded \return 1 Function failed */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) { uint32_t result; @@ -640,7 +1115,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, \return 0 Function succeeded \return 1 Function failed */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) { uint32_t result; @@ -657,7 +1132,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, \return 0 Function succeeded \return 1 Function failed */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) { uint32_t result; @@ -670,22 +1145,31 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, \brief Remove the exclusive lock \details Removes the exclusive lock which is created by LDREX. */ -__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) +__STATIC_FORCEINLINE void __CLREX(void) { __ASM volatile ("clrex" ::: "memory"); } +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) /** \brief Signed Saturate \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) \return Saturated value */ #define __SSAT(ARG1,ARG2) \ +__extension__ \ ({ \ - uint32_t __RES, __ARG1 = (ARG1); \ + int32_t __RES, __ARG1 = (ARG1); \ __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ __RES; \ }) @@ -694,11 +1178,12 @@ __attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) /** \brief Unsigned Saturate \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) \return Saturated value */ #define __USAT(ARG1,ARG2) \ + __extension__ \ ({ \ uint32_t __RES, __ARG1 = (ARG1); \ __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ @@ -713,7 +1198,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) \param [in] value Value to rotate \return Rotated value */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) { uint32_t result; @@ -728,17 +1213,17 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) \param [in] ptr Pointer to data \return value of type uint8_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) { uint32_t result; #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); #else /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not accepted by assembler. So has to use following less efficient pattern. */ - __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); #endif return ((uint8_t) result); /* Add explicit type cast here */ } @@ -750,17 +1235,17 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t \param [in] ptr Pointer to data \return value of type uint16_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) { uint32_t result; #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); #else /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not accepted by assembler. So has to use following less efficient pattern. */ - __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); #endif return ((uint16_t) result); /* Add explicit type cast here */ } @@ -772,11 +1257,11 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_ \param [in] ptr Pointer to data \return value of type uint32_t at (*ptr) */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) { uint32_t result; - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); return(result); } @@ -787,9 +1272,9 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } @@ -799,9 +1284,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volat \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) { - __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } @@ -811,12 +1296,249 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, vola \param [in] value Value to store \param [in] ptr Pointer to location */ -__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) { - __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); } -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ @@ -827,9 +1549,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volat @{ */ -#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -837,7 +1559,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -845,7 +1567,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -853,7 +1575,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -861,7 +1583,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -869,7 +1591,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -878,7 +1600,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -886,7 +1608,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -894,7 +1616,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -902,7 +1624,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -910,7 +1632,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -918,7 +1640,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -927,7 +1649,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -935,7 +1657,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -943,7 +1665,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -951,7 +1673,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -959,7 +1681,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -967,7 +1689,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -975,7 +1697,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -983,7 +1705,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -991,7 +1713,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -999,7 +1721,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1007,7 +1729,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1015,7 +1737,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1023,7 +1745,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1031,7 +1753,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1039,7 +1761,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1047,7 +1769,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1055,7 +1777,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1063,7 +1785,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1071,7 +1793,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1079,7 +1801,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1087,7 +1809,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1095,7 +1817,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1103,7 +1825,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1111,7 +1833,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1119,7 +1841,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1127,7 +1849,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1149,7 +1871,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op __RES; \ }) -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) { uint32_t result; @@ -1157,7 +1879,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1165,7 +1887,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) { uint32_t result; @@ -1173,7 +1895,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) { uint32_t result; @@ -1181,7 +1903,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1189,7 +1911,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1197,7 +1919,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1205,7 +1927,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1213,7 +1935,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1230,7 +1952,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t o return(llr.w64); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1247,7 +1969,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t return(llr.w64); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1255,7 +1977,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1263,7 +1985,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1271,7 +1993,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) { uint32_t result; @@ -1279,7 +2001,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t o return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1296,7 +2018,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t o return(llr.w64); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) { union llreg_u{ uint32_t w32[2]; @@ -1313,7 +2035,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t return(llr.w64); } -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) { uint32_t result; @@ -1321,7 +2043,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1 return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) { int32_t result; @@ -1329,7 +2051,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, return(result); } -__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) { int32_t result; @@ -1337,6 +2059,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, return(result); } +#if 0 #define __PKHBT(ARG1,ARG2,ARG3) \ ({ \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ @@ -1353,8 +2076,15 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ __RES; \ }) +#endif -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) { int32_t result; @@ -1362,12 +2092,10 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1 return(result); } -#endif /* (__CORTEX_M >= 0x04) */ +#endif /* (__ARM_FEATURE_DSP == 1) */ /*@} end of group CMSIS_SIMD_intrinsics */ -#if defined ( __GNUC__ ) #pragma GCC diagnostic pop -#endif #endif /* __CMSIS_GCC_H */ diff --git a/lib/cmsis/inc/cmsis_iccarm.h b/lib/cmsis/inc/cmsis_iccarm.h new file mode 100644 index 0000000000000..20b50ce380d6c --- /dev/null +++ b/lib/cmsis/inc/cmsis_iccarm.h @@ -0,0 +1,940 @@ +/**************************************************************************//** + * @file cmsis_iccarm.h + * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file + * @version V5.0.8 + * @date 04. September 2018 + ******************************************************************************/ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2017-2018 IAR Systems +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------ + + +#ifndef __CMSIS_ICCARM_H__ +#define __CMSIS_ICCARM_H__ + +#ifndef __ICCARM__ + #error This file should only be compiled by ICCARM +#endif + +#pragma system_include + +#define __IAR_FT _Pragma("inline=forced") __intrinsic + +#if (__VER__ >= 8000000) + #define __ICCARM_V8 1 +#else + #define __ICCARM_V8 0 +#endif + +#ifndef __ALIGNED + #if __ICCARM_V8 + #define __ALIGNED(x) __attribute__((aligned(x))) + #elif (__VER__ >= 7080000) + /* Needs IAR language extensions */ + #define __ALIGNED(x) __attribute__((aligned(x))) + #else + #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. + #define __ALIGNED(x) + #endif +#endif + + +/* Define compiler macros for CPU architecture, used in CMSIS 5. + */ +#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__ +/* Macros already defined */ +#else + #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M' + #if __ARM_ARCH == 6 + #define __ARM_ARCH_6M__ 1 + #elif __ARM_ARCH == 7 + #if __ARM_FEATURE_DSP + #define __ARM_ARCH_7EM__ 1 + #else + #define __ARM_ARCH_7M__ 1 + #endif + #endif /* __ARM_ARCH */ + #endif /* __ARM_ARCH_PROFILE == 'M' */ +#endif + +/* Alternativ core deduction for older ICCARM's */ +#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \ + !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__) + #if defined(__ARM6M__) && (__CORE__ == __ARM6M__) + #define __ARM_ARCH_6M__ 1 + #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__) + #define __ARM_ARCH_7M__ 1 + #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__) + #define __ARM_ARCH_7EM__ 1 + #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #else + #error "Unknown target." + #endif +#endif + + + +#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1 + #define __IAR_M0_FAMILY 1 +#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1 + #define __IAR_M0_FAMILY 1 +#else + #define __IAR_M0_FAMILY 0 +#endif + + +#ifndef __ASM + #define __ASM __asm +#endif + +#ifndef __INLINE + #define __INLINE inline +#endif + +#ifndef __NO_RETURN + #if __ICCARM_V8 + #define __NO_RETURN __attribute__((__noreturn__)) + #else + #define __NO_RETURN _Pragma("object_attribute=__noreturn") + #endif +#endif + +#ifndef __PACKED + #if __ICCARM_V8 + #define __PACKED __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED __packed + #endif +#endif + +#ifndef __PACKED_STRUCT + #if __ICCARM_V8 + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_STRUCT __packed struct + #endif +#endif + +#ifndef __PACKED_UNION + #if __ICCARM_V8 + #define __PACKED_UNION union __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_UNION __packed union + #endif +#endif + +#ifndef __RESTRICT + #if __ICCARM_V8 + #define __RESTRICT __restrict + #else + /* Needs IAR language extensions */ + #define __RESTRICT restrict + #endif +#endif + +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif + +#ifndef __FORCEINLINE + #define __FORCEINLINE _Pragma("inline=forced") +#endif + +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE +#endif + +#ifndef __UNALIGNED_UINT16_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint16_t __iar_uint16_read(void const *ptr) +{ + return *(__packed uint16_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR) +#endif + + +#ifndef __UNALIGNED_UINT16_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val) +{ + *(__packed uint16_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint32_t __iar_uint32_read(void const *ptr) +{ + return *(__packed uint32_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR) +#endif + +#ifndef __UNALIGNED_UINT32_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val) +{ + *(__packed uint32_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32 /* deprecated */ +#pragma language=save +#pragma language=extended +__packed struct __iar_u32 { uint32_t v; }; +#pragma language=restore +#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v) +#endif + +#ifndef __USED + #if __ICCARM_V8 + #define __USED __attribute__((used)) + #else + #define __USED _Pragma("__root") + #endif +#endif + +#ifndef __WEAK + #if __ICCARM_V8 + #define __WEAK __attribute__((weak)) + #else + #define __WEAK _Pragma("__weak") + #endif +#endif + + +#ifndef __ICCARM_INTRINSICS_VERSION__ + #define __ICCARM_INTRINSICS_VERSION__ 0 +#endif + +#if __ICCARM_INTRINSICS_VERSION__ == 2 + + #if defined(__CLZ) + #undef __CLZ + #endif + #if defined(__REVSH) + #undef __REVSH + #endif + #if defined(__RBIT) + #undef __RBIT + #endif + #if defined(__SSAT) + #undef __SSAT + #endif + #if defined(__USAT) + #undef __USAT + #endif + + #include "iccarm_builtin.h" + + #define __disable_fault_irq __iar_builtin_disable_fiq + #define __disable_irq __iar_builtin_disable_interrupt + #define __enable_fault_irq __iar_builtin_enable_fiq + #define __enable_irq __iar_builtin_enable_interrupt + #define __arm_rsr __iar_builtin_rsr + #define __arm_wsr __iar_builtin_wsr + + + #define __get_APSR() (__arm_rsr("APSR")) + #define __get_BASEPRI() (__arm_rsr("BASEPRI")) + #define __get_CONTROL() (__arm_rsr("CONTROL")) + #define __get_FAULTMASK() (__arm_rsr("FAULTMASK")) + + #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + #define __get_FPSCR() (__arm_rsr("FPSCR")) + #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE))) + #else + #define __get_FPSCR() ( 0 ) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #define __get_IPSR() (__arm_rsr("IPSR")) + #define __get_MSP() (__arm_rsr("MSP")) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __get_MSPLIM() (0U) + #else + #define __get_MSPLIM() (__arm_rsr("MSPLIM")) + #endif + #define __get_PRIMASK() (__arm_rsr("PRIMASK")) + #define __get_PSP() (__arm_rsr("PSP")) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __get_PSPLIM() (0U) + #else + #define __get_PSPLIM() (__arm_rsr("PSPLIM")) + #endif + + #define __get_xPSR() (__arm_rsr("xPSR")) + + #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE))) + #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE))) + #define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE))) + #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE))) + #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __set_MSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE))) + #endif + #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE))) + #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE))) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __set_PSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE))) + #endif + + #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS")) + #define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE))) + #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS")) + #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE))) + #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS")) + #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE))) + #define __TZ_get_SP_NS() (__arm_rsr("SP_NS")) + #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE))) + #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS")) + #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE))) + #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS")) + #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE))) + #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS")) + #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __TZ_get_PSPLIM_NS() (0U) + #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE)) + #else + #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS")) + #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE))) + #endif + + #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS")) + #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE))) + + #define __NOP __iar_builtin_no_operation + + #define __CLZ __iar_builtin_CLZ + #define __CLREX __iar_builtin_CLREX + + #define __DMB __iar_builtin_DMB + #define __DSB __iar_builtin_DSB + #define __ISB __iar_builtin_ISB + + #define __LDREXB __iar_builtin_LDREXB + #define __LDREXH __iar_builtin_LDREXH + #define __LDREXW __iar_builtin_LDREX + + #define __RBIT __iar_builtin_RBIT + #define __REV __iar_builtin_REV + #define __REV16 __iar_builtin_REV16 + + __IAR_FT int16_t __REVSH(int16_t val) + { + return (int16_t) __iar_builtin_REVSH(val); + } + + #define __ROR __iar_builtin_ROR + #define __RRX __iar_builtin_RRX + + #define __SEV __iar_builtin_SEV + + #if !__IAR_M0_FAMILY + #define __SSAT __iar_builtin_SSAT + #endif + + #define __STREXB __iar_builtin_STREXB + #define __STREXH __iar_builtin_STREXH + #define __STREXW __iar_builtin_STREX + + #if !__IAR_M0_FAMILY + #define __USAT __iar_builtin_USAT + #endif + + #define __WFE __iar_builtin_WFE + #define __WFI __iar_builtin_WFI + + #if __ARM_MEDIA__ + #define __SADD8 __iar_builtin_SADD8 + #define __QADD8 __iar_builtin_QADD8 + #define __SHADD8 __iar_builtin_SHADD8 + #define __UADD8 __iar_builtin_UADD8 + #define __UQADD8 __iar_builtin_UQADD8 + #define __UHADD8 __iar_builtin_UHADD8 + #define __SSUB8 __iar_builtin_SSUB8 + #define __QSUB8 __iar_builtin_QSUB8 + #define __SHSUB8 __iar_builtin_SHSUB8 + #define __USUB8 __iar_builtin_USUB8 + #define __UQSUB8 __iar_builtin_UQSUB8 + #define __UHSUB8 __iar_builtin_UHSUB8 + #define __SADD16 __iar_builtin_SADD16 + #define __QADD16 __iar_builtin_QADD16 + #define __SHADD16 __iar_builtin_SHADD16 + #define __UADD16 __iar_builtin_UADD16 + #define __UQADD16 __iar_builtin_UQADD16 + #define __UHADD16 __iar_builtin_UHADD16 + #define __SSUB16 __iar_builtin_SSUB16 + #define __QSUB16 __iar_builtin_QSUB16 + #define __SHSUB16 __iar_builtin_SHSUB16 + #define __USUB16 __iar_builtin_USUB16 + #define __UQSUB16 __iar_builtin_UQSUB16 + #define __UHSUB16 __iar_builtin_UHSUB16 + #define __SASX __iar_builtin_SASX + #define __QASX __iar_builtin_QASX + #define __SHASX __iar_builtin_SHASX + #define __UASX __iar_builtin_UASX + #define __UQASX __iar_builtin_UQASX + #define __UHASX __iar_builtin_UHASX + #define __SSAX __iar_builtin_SSAX + #define __QSAX __iar_builtin_QSAX + #define __SHSAX __iar_builtin_SHSAX + #define __USAX __iar_builtin_USAX + #define __UQSAX __iar_builtin_UQSAX + #define __UHSAX __iar_builtin_UHSAX + #define __USAD8 __iar_builtin_USAD8 + #define __USADA8 __iar_builtin_USADA8 + #define __SSAT16 __iar_builtin_SSAT16 + #define __USAT16 __iar_builtin_USAT16 + #define __UXTB16 __iar_builtin_UXTB16 + #define __UXTAB16 __iar_builtin_UXTAB16 + #define __SXTB16 __iar_builtin_SXTB16 + #define __SXTAB16 __iar_builtin_SXTAB16 + #define __SMUAD __iar_builtin_SMUAD + #define __SMUADX __iar_builtin_SMUADX + #define __SMMLA __iar_builtin_SMMLA + #define __SMLAD __iar_builtin_SMLAD + #define __SMLADX __iar_builtin_SMLADX + #define __SMLALD __iar_builtin_SMLALD + #define __SMLALDX __iar_builtin_SMLALDX + #define __SMUSD __iar_builtin_SMUSD + #define __SMUSDX __iar_builtin_SMUSDX + #define __SMLSD __iar_builtin_SMLSD + #define __SMLSDX __iar_builtin_SMLSDX + #define __SMLSLD __iar_builtin_SMLSLD + #define __SMLSLDX __iar_builtin_SMLSLDX + #define __SEL __iar_builtin_SEL + #define __QADD __iar_builtin_QADD + #define __QSUB __iar_builtin_QSUB + #define __PKHBT __iar_builtin_PKHBT + #define __PKHTB __iar_builtin_PKHTB + #endif + +#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #define __CLZ __cmsis_iar_clz_not_active + #define __SSAT __cmsis_iar_ssat_not_active + #define __USAT __cmsis_iar_usat_not_active + #define __RBIT __cmsis_iar_rbit_not_active + #define __get_APSR __cmsis_iar_get_APSR_not_active + #endif + + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #define __get_FPSCR __cmsis_iar_get_FPSR_not_active + #define __set_FPSCR __cmsis_iar_set_FPSR_not_active + #endif + + #ifdef __INTRINSICS_INCLUDED + #error intrinsics.h is already included previously! + #endif + + #include + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #undef __CLZ + #undef __SSAT + #undef __USAT + #undef __RBIT + #undef __get_APSR + + __STATIC_INLINE uint8_t __CLZ(uint32_t data) + { + if (data == 0U) { return 32U; } + + uint32_t count = 0U; + uint32_t mask = 0x80000000U; + + while ((data & mask) == 0U) + { + count += 1U; + mask = mask >> 1U; + } + return count; + } + + __STATIC_INLINE uint32_t __RBIT(uint32_t v) + { + uint8_t sc = 31U; + uint32_t r = v; + for (v >>= 1U; v; v >>= 1U) + { + r <<= 1U; + r |= v & 1U; + sc--; + } + return (r << sc); + } + + __STATIC_INLINE uint32_t __get_APSR(void) + { + uint32_t res; + __asm("MRS %0,APSR" : "=r" (res)); + return res; + } + + #endif + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #undef __get_FPSCR + #undef __set_FPSCR + #define __get_FPSCR() (0) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #pragma diag_suppress=Pe940 + #pragma diag_suppress=Pe177 + + #define __enable_irq __enable_interrupt + #define __disable_irq __disable_interrupt + #define __NOP __no_operation + + #define __get_xPSR __get_PSR + + #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0) + + __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr) + { + return __LDREX((unsigned long *)ptr); + } + + __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr) + { + return __STREX(value, (unsigned long *)ptr); + } + #endif + + + /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + #if (__CORTEX_M >= 0x03) + + __IAR_FT uint32_t __RRX(uint32_t value) + { + uint32_t result; + __ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc"); + return(result); + } + + __IAR_FT void __set_BASEPRI_MAX(uint32_t value) + { + __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value)); + } + + + #define __enable_fault_irq __enable_fiq + #define __disable_fault_irq __disable_fiq + + + #endif /* (__CORTEX_M >= 0x03) */ + + __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2) + { + return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2)); + } + + #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + __IAR_FT uint32_t __get_MSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,MSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_MSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR MSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __get_PSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_PSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_CONTROL_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,CONTROL_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value) + { + __asm volatile("MSR CONTROL_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PSP_NS(uint32_t value) + { + __asm volatile("MSR PSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_MSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSP_NS(uint32_t value) + { + __asm volatile("MSR MSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_SP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,SP_NS" : "=r" (res)); + return res; + } + __IAR_FT void __TZ_set_SP_NS(uint32_t value) + { + __asm volatile("MSR SP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value) + { + __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value) + { + __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value) + { + __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value) + { + __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value)); + } + + #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + +#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value)) + +#if __IAR_M0_FAMILY + __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) + { + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; + } + + __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) + { + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; + } +#endif + +#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + + __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr) + { + uint32_t res; + __ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr) + { + uint32_t res; + __ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDRT(volatile uint32_t *addr) + { + uint32_t res; + __ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return res; + } + + __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr) + { + __ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr) + { + __ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr) + { + __ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory"); + } + +#endif /* (__CORTEX_M >= 0x03) */ + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + + __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDA(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr) + { + __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr) + { + __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr) + { + __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + +#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#undef __IAR_FT +#undef __IAR_M0_FAMILY +#undef __ICCARM_V8 + +#pragma diag_default=Pe940 +#pragma diag_default=Pe177 + +#endif /* __CMSIS_ICCARM_H__ */ diff --git a/lib/cmsis/inc/cmsis_version.h b/lib/cmsis/inc/cmsis_version.h new file mode 100644 index 0000000000000..660f612aa31fe --- /dev/null +++ b/lib/cmsis/inc/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.2 + * @date 19. April 2017 + ******************************************************************************/ +/* + * Copyright (c) 2009-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif diff --git a/lib/cmsis/inc/core_armv81mml.h b/lib/cmsis/inc/core_armv81mml.h new file mode 100644 index 0000000000000..db6d9f23638b6 --- /dev/null +++ b/lib/cmsis/inc/core_armv81mml.h @@ -0,0 +1,2967 @@ +/**************************************************************************//** + * @file core_armv81mml.h + * @brief CMSIS Armv8.1-M Mainline Core Peripheral Access Layer Header File + * @version V1.0.0 + * @date 15. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2018-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV81MML_H_GENERIC +#define __CORE_ARMV81MML_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMV81MML + @{ + */ + +#include "cmsis_version.h" + +#define __ARM_ARCH_8M_MAIN__ 1 // patching for now +/* CMSIS ARMV81MML definitions */ +#define __ARMv81MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv81MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv81MML_CMSIS_VERSION ((__ARMv81MML_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv81MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (81U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV81MML_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV81MML_H_DEPENDANT +#define __CORE_ARMV81MML_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv81MML_REV + #define __ARMv81MML_REV 0x0000U + #warning "__ARMv81MML_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv81MML */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_PXN_Pos 4U /*!< MPU RLAR: PXN Position */ +#define MPU_RLAR_PXN_Msk (0x1UL << MPU_RLAR_PXN_Pos) /*!< MPU RLAR: PXN Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV81MML_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis/inc/core_armv8mbl.h b/lib/cmsis/inc/core_armv8mbl.h new file mode 100644 index 0000000000000..57d9f663fd3ed --- /dev/null +++ b/lib/cmsis/inc/core_armv8mbl.h @@ -0,0 +1,1918 @@ +/**************************************************************************//** + * @file core_armv8mbl.h + * @brief CMSIS Armv8-M Baseline Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV8MBL_H_GENERIC +#define __CORE_ARMV8MBL_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMv8MBL + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS definitions */ +#define __ARMv8MBL_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv8MBL_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M ( 2U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MBL_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV8MBL_H_DEPENDANT +#define __CORE_ARMV8MBL_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv8MBL_REV + #define __ARMv8MBL_REV 0x0000U + #warning "__ARMv8MBL_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif + + #ifndef __ETM_PRESENT + #define __ETM_PRESENT 0U + #warning "__ETM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MTB_PRESENT + #define __MTB_PRESENT 0U + #warning "__MTB_PRESENT not defined in device header file; using default!" + #endif + +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv8MBL */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + uint32_t RESERVED0[6U]; + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[809U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ + uint32_t RESERVED4[4U]; + __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ +#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI Periodic Synchronization Control Register Definitions */ +#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ +#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ + +/* TPI Software Lock Status Register Definitions */ +#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ +#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ + +#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ +#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ + +#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ +#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + uint32_t RESERVED0[7U]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 1U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#endif +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */ +#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + If VTOR is not present address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MBL_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis/inc/core_armv8mml.h b/lib/cmsis/inc/core_armv8mml.h new file mode 100644 index 0000000000000..30aab58722fc8 --- /dev/null +++ b/lib/cmsis/inc/core_armv8mml.h @@ -0,0 +1,2832 @@ +/**************************************************************************//** + * @file core_armv8mml.h + * @brief CMSIS Armv8-M Mainline Core Peripheral Access Layer Header File + * @version V5.1.0 + * @date 12. September 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV8MML_H_GENERIC +#define __CORE_ARMV8MML_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMv8MML + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS Armv8MML definitions */ +#define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (81U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MML_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV8MML_H_DEPENDANT +#define __CORE_ARMV8MML_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv8MML_REV + #define __ARMv8MML_REV 0x0000U + #warning "__ARMv8MML_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv8MML */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[809U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ + uint32_t RESERVED4[4U]; + __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ +#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI Periodic Synchronization Control Register Definitions */ +#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ +#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ + +/* TPI Software Lock Status Register Definitions */ +#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ +#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ + +#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ +#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ + +#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ +#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MML_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis/inc/core_cm0.h b/lib/cmsis/inc/core_cm0.h index 711dad5517027..fcf27578ccf59 100644 --- a/lib/cmsis/inc/core_cm0.h +++ b/lib/cmsis/inc/core_cm0.h @@ -1,40 +1,30 @@ /**************************************************************************//** * @file core_cm0.h * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 + * @version V5.0.6 + * @date 13. March 2019 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif @@ -70,53 +60,15 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM0 definitions */ -#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ - __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline + __CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline - -#else - #error Unknown compiler -#endif +#define __CORTEX_M (0U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all @@ -128,8 +80,8 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -143,7 +95,7 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined ( __TMS470__ ) +#elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -160,8 +112,8 @@ #endif -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + #ifdef __cplusplus } @@ -364,7 +316,7 @@ typedef struct __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[31U]; __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[31U]; + uint32_t RESERVED1[31U]; __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[31U]; __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ @@ -555,18 +507,18 @@ typedef struct /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. - \param[in] value Value of register. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ @@ -578,7 +530,7 @@ typedef struct @{ */ -/* Memory mapping of Cortex-M0 Hardware */ +/* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ @@ -614,87 +566,177 @@ typedef struct @{ */ -/* Interrupt Priorities are WORD accessible only under ARMv6M */ +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) /** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } /** \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { - NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } @@ -702,32 +744,116 @@ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) /** \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { - return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + Address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = 0x0U; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = 0x0U; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ -__STATIC_INLINE void NVIC_SystemReset(void) +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ @@ -744,6 +870,31 @@ __STATIC_INLINE void NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + /* ################################## SysTick function ############################################ */ /** @@ -753,7 +904,7 @@ __STATIC_INLINE void NVIC_SystemReset(void) @{ */ -#if (__Vendor_SysTickConfig == 0U) +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration diff --git a/lib/cmsis/inc/core_cm0plus.h b/lib/cmsis/inc/core_cm0plus.h index b04aa3905323c..65ea443095f08 100644 --- a/lib/cmsis/inc/core_cm0plus.h +++ b/lib/cmsis/inc/core_cm0plus.h @@ -1,40 +1,30 @@ /**************************************************************************//** * @file core_cm0plus.h * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 + * @version V5.0.7 + * @date 13. March 2019 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif @@ -70,53 +60,15 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM0+ definitions */ -#define __CM0PLUS_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __CM0PLUS_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \ - __CM0PLUS_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline + __CM0PLUS_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ -#else - #error Unknown compiler -#endif +#define __CORTEX_M (0U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all @@ -128,8 +80,8 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -143,7 +95,7 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined ( __TMS470__ ) +#elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -160,8 +112,8 @@ #endif -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + #ifdef __cplusplus } @@ -378,7 +330,7 @@ typedef struct __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[31U]; __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[31U]; + uint32_t RESERVED1[31U]; __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[31U]; __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ @@ -404,7 +356,7 @@ typedef struct { __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ -#if (__VTOR_PRESENT == 1U) +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ #else uint32_t RESERVED0; @@ -461,7 +413,7 @@ typedef struct #define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ -#if (__VTOR_PRESENT == 1U) +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) /* SCB Interrupt Control State Register Definitions */ #define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */ #define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ @@ -558,7 +510,7 @@ typedef struct /*@} end of group CMSIS_SysTick */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) @@ -578,6 +530,8 @@ typedef struct __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ } MPU_Type; +#define MPU_TYPE_RALIASES 1U + /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ @@ -667,18 +621,18 @@ typedef struct /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. - \param[in] value Value of register. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ @@ -690,7 +644,7 @@ typedef struct @{ */ -/* Memory mapping of Cortex-M0+ Hardware */ +/* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ @@ -700,7 +654,7 @@ typedef struct #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif @@ -730,87 +684,177 @@ typedef struct @{ */ -/* Interrupt Priorities are WORD accessible only under ARMv6M */ +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0+ */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) #define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) /** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } /** \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { - NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } @@ -818,32 +862,124 @@ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) /** \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { - return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + If VTOR is not present address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t vectors = SCB->VTOR; +#else + uint32_t vectors = 0x0U; +#endif + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t vectors = SCB->VTOR; +#else + uint32_t vectors = 0x0U; +#endif + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ -__STATIC_INLINE void NVIC_SystemReset(void) +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ @@ -859,6 +995,38 @@ __STATIC_INLINE void NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + /* ################################## SysTick function ############################################ */ @@ -869,7 +1037,7 @@ __STATIC_INLINE void NVIC_SystemReset(void) @{ */ -#if (__Vendor_SysTickConfig == 0U) +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration diff --git a/lib/cmsis/inc/core_cm1.h b/lib/cmsis/inc/core_cm1.h new file mode 100644 index 0000000000000..72c515cb092e0 --- /dev/null +++ b/lib/cmsis/inc/core_cm1.h @@ -0,0 +1,976 @@ +/**************************************************************************//** + * @file core_cm1.h + * @brief CMSIS Cortex-M1 Core Peripheral Access Layer Header File + * @version V1.0.1 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM1_H_GENERIC +#define __CORE_CM1_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M1 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM1 definitions */ +#define __CM1_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM1_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM1_CMSIS_VERSION ((__CM1_CMSIS_VERSION_MAIN << 16U) | \ + __CM1_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (1U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM1_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM1_H_DEPENDANT +#define __CORE_CM1_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM1_REV + #define __CM1_REV 0x0100U + #warning "__CM1_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M1 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_ITCMUAEN_Pos 4U /*!< ACTLR: Instruction TCM Upper Alias Enable Position */ +#define SCnSCB_ACTLR_ITCMUAEN_Msk (1UL << SCnSCB_ACTLR_ITCMUAEN_Pos) /*!< ACTLR: Instruction TCM Upper Alias Enable Mask */ + +#define SCnSCB_ACTLR_ITCMLAEN_Pos 3U /*!< ACTLR: Instruction TCM Lower Alias Enable Position */ +#define SCnSCB_ACTLR_ITCMLAEN_Msk (1UL << SCnSCB_ACTLR_ITCMLAEN_Pos) /*!< ACTLR: Instruction TCM Lower Alias Enable Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M1 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M1 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M1 */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + Address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)0x0U; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)0x0U; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM1_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis/inc/core_cm23.h b/lib/cmsis/inc/core_cm23.h new file mode 100644 index 0000000000000..26fe163a0e82c --- /dev/null +++ b/lib/cmsis/inc/core_cm23.h @@ -0,0 +1,1993 @@ +/**************************************************************************//** + * @file core_cm23.h + * @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM23_H_GENERIC +#define __CORE_CM23_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M23 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS definitions */ +#define __CM23_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM23_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM23_CMSIS_VERSION ((__CM23_CMSIS_VERSION_MAIN << 16U) | \ + __CM23_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (23U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM23_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM23_H_DEPENDANT +#define __CORE_CM23_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM23_REV + #define __CM23_REV 0x0000U + #warning "__CM23_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif + + #ifndef __ETM_PRESENT + #define __ETM_PRESENT 0U + #warning "__ETM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MTB_PRESENT + #define __MTB_PRESENT 0U + #warning "__MTB_PRESENT not defined in device header file; using default!" + #endif + +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M23 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + uint32_t RESERVED0[6U]; + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ + __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ + __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration Test FIFO Test Data 0 Register Definitions */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ +#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ +#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ +#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ + +/* TPI Integration Test ATB Control Register 2 Register Definitions */ +#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ +#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ + +#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ +#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ + +#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ +#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ + +#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ +#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ + +/* TPI Integration Test FIFO Test Data 1 Register Definitions */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ +#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ +#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ +#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ + +/* TPI Integration Test ATB Control Register 0 Definitions */ +#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ +#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ + +#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ +#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ + +#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ +#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ + +#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ +#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + uint32_t RESERVED0[7U]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 1U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#endif +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */ +#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else +/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M23 */ +/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M23 */ + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + If VTOR is not present address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM23_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis/inc/core_cm3.h b/lib/cmsis/inc/core_cm3.h index b4ac4c7b05a79..ea5405088c3ef 100644 --- a/lib/cmsis/inc/core_cm3.h +++ b/lib/cmsis/inc/core_cm3.h @@ -1,40 +1,30 @@ /**************************************************************************//** * @file core_cm3.h * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 + * @version V5.1.0 + * @date 13. March 2019 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif @@ -70,53 +60,15 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS CM3 definitions */ -#define __CM3_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __CM3_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ - __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x03U) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline + __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ -#else - #error Unknown compiler -#endif +#define __CORTEX_M (3U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all @@ -128,8 +80,8 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -143,7 +95,7 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined ( __TMS470__ ) +#elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -160,8 +112,8 @@ #endif -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + #ifdef __cplusplus } @@ -191,7 +143,7 @@ #endif #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 4U + #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif @@ -308,9 +260,11 @@ typedef union struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ @@ -336,12 +290,15 @@ typedef union #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ -#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ -#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ @@ -385,7 +342,7 @@ typedef struct __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24U]; + uint32_t RESERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ @@ -487,7 +444,7 @@ typedef struct #define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ /* SCB Vector Table Offset Register Definitions */ -#if (__CM3_REV < 0x0201U) /* core r2p1 */ +#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */ #define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ #define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ @@ -602,6 +559,60 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ @@ -645,7 +656,7 @@ typedef struct { uint32_t RESERVED0[1U]; __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ -#if ((defined __CM3_REV) && (__CM3_REV >= 0x200U)) +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ #else uint32_t RESERVED1[1U]; @@ -657,6 +668,12 @@ typedef struct #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /* Auxiliary Control Register Definitions */ +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ #define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ #define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ @@ -666,6 +683,7 @@ typedef struct #define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ #define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ +#endif /*@} end of group CMSIS_SCnotSCB */ @@ -746,10 +764,7 @@ typedef struct __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ @@ -770,7 +785,7 @@ typedef struct /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ @@ -800,18 +815,6 @@ typedef struct #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ - /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ @@ -984,7 +987,7 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ @@ -995,7 +998,7 @@ typedef struct __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; @@ -1044,13 +1047,13 @@ typedef struct /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ @@ -1065,18 +1068,21 @@ typedef struct #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ @@ -1091,12 +1097,15 @@ typedef struct #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ @@ -1118,16 +1127,16 @@ typedef struct #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + /*@}*/ /* end of group CMSIS_TPI */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) @@ -1153,6 +1162,8 @@ typedef struct __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; +#define MPU_TYPE_RALIASES 4U + /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ @@ -1337,18 +1348,18 @@ typedef struct /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. - \param[in] value Value of register. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ @@ -1360,7 +1371,7 @@ typedef struct @{ */ -/* Memory mapping of Cortex-M3 Hardware */ +/* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ @@ -1379,7 +1390,7 @@ typedef struct #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif @@ -1410,6 +1421,45 @@ typedef struct @{ */ +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. @@ -1419,7 +1469,7 @@ typedef struct priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ @@ -1428,7 +1478,7 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } @@ -1438,121 +1488,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } /** \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Get Active Interrupt - \details Reads the active register in NVIC and returns the active bit. - \param [in] IRQn Interrupt number. + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { - NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { - return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } @@ -1609,11 +1716,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr } +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ -__STATIC_INLINE void NVIC_SystemReset(void) +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ @@ -1630,6 +1768,39 @@ __STATIC_INLINE void NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + /* ################################## SysTick function ############################################ */ @@ -1640,7 +1811,7 @@ __STATIC_INLINE void NVIC_SystemReset(void) @{ */ -#if (__Vendor_SysTickConfig == 0U) +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration @@ -1683,8 +1854,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) @{ */ -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** diff --git a/lib/cmsis/inc/core_cm33.h b/lib/cmsis/inc/core_cm33.h new file mode 100644 index 0000000000000..d5d97a96f2d6b --- /dev/null +++ b/lib/cmsis/inc/core_cm33.h @@ -0,0 +1,2907 @@ +/**************************************************************************//** + * @file core_cm33.h + * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File + * @version V5.1.0 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM33_H_GENERIC +#define __CORE_CM33_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M33 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM33 definitions */ +#define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM33_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM33_CMSIS_VERSION ((__CM33_CMSIS_VERSION_MAIN << 16U) | \ + __CM33_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (33U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined (__TARGET_FPU_VFP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined (__ARM_FP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined (__ARMVFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined (__TI_VFP_SUPPORT__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined (__FPU_VFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM33_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM33_H_DEPENDANT +#define __CORE_CM33_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM33_REV + #define __CM33_REV 0x0000U + #warning "__CM33_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M33 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ + __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ + __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration Test FIFO Test Data 0 Register Definitions */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ +#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ +#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ +#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ + +/* TPI Integration Test ATB Control Register 2 Register Definitions */ +#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ +#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ + +#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ +#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ + +#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ +#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ + +#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ +#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ + +/* TPI Integration Test FIFO Test Data 1 Register Definitions */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ +#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ +#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ +#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ + +/* TPI Integration Test ATB Control Register 0 Definitions */ +#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ +#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ + +#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ +#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ + +#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ +#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ + +#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ +#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM33_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis/inc/core_cm35p.h b/lib/cmsis/inc/core_cm35p.h new file mode 100644 index 0000000000000..c00e54ca7a984 --- /dev/null +++ b/lib/cmsis/inc/core_cm35p.h @@ -0,0 +1,2907 @@ +/**************************************************************************//** + * @file core_cm35p.h + * @brief CMSIS Cortex-M35P Core Peripheral Access Layer Header File + * @version V1.0.0 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM35P_H_GENERIC +#define __CORE_CM35P_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M35P + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM35P definitions */ +#define __CM35P_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM35P_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM35P_CMSIS_VERSION ((__CM35P_CMSIS_VERSION_MAIN << 16U) | \ + __CM35P_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (35U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined (__TARGET_FPU_VFP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined (__ARM_FP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined (__ARMVFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined (__TI_VFP_SUPPORT__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined (__FPU_VFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM35P_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM35P_H_DEPENDANT +#define __CORE_CM35P_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM35P_REV + #define __CM35P_REV 0x0000U + #warning "__CM35P_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M35P */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ + __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ + __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration Test FIFO Test Data 0 Register Definitions */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ +#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ +#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ +#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ + +/* TPI Integration Test ATB Control Register 2 Register Definitions */ +#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ +#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ + +#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ +#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ + +#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ +#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ + +#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ +#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ + +/* TPI Integration Test FIFO Test Data 1 Register Definitions */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ +#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ +#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ +#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ + +/* TPI Integration Test ATB Control Register 0 Definitions */ +#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ +#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ + +#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ +#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ + +#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ +#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ + +#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ +#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM35P_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis/inc/core_cm4.h b/lib/cmsis/inc/core_cm4.h index dc840ebf22213..f205b333f321c 100644 --- a/lib/cmsis/inc/core_cm4.h +++ b/lib/cmsis/inc/core_cm4.h @@ -1,40 +1,30 @@ /**************************************************************************//** * @file core_cm4.h * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 + * @version V5.1.0 + * @date 13. March 2019 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif @@ -70,60 +60,22 @@ @{ */ -/* CMSIS CM4 definitions */ -#define __CM4_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __CM4_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ -#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ - __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x04U) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline +#include "cmsis_version.h" -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline - -#else - #error Unknown compiler -#endif +#define __CORTEX_M (4U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -133,9 +85,9 @@ #define __FPU_USED 0U #endif -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #if (__FPU_PRESENT == 1) +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -147,7 +99,7 @@ #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -159,7 +111,7 @@ #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -169,9 +121,9 @@ #define __FPU_USED 0U #endif -#elif defined ( __TMS470__ ) +#elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -183,7 +135,7 @@ #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -195,7 +147,7 @@ #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -207,9 +159,8 @@ #endif -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ -#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + #ifdef __cplusplus } @@ -244,7 +195,7 @@ #endif #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 4U + #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif @@ -367,11 +318,12 @@ typedef union struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ @@ -397,8 +349,8 @@ typedef union #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ -#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ -#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ @@ -406,6 +358,9 @@ typedef union #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ @@ -453,7 +408,7 @@ typedef struct __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24U]; + uint32_t RESERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ @@ -662,6 +617,66 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ @@ -807,10 +822,7 @@ typedef struct __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ @@ -831,7 +843,7 @@ typedef struct /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ @@ -861,18 +873,6 @@ typedef struct #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ - /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ @@ -1045,7 +1045,7 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ @@ -1056,7 +1056,7 @@ typedef struct __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; @@ -1105,13 +1105,13 @@ typedef struct /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ @@ -1126,18 +1126,21 @@ typedef struct #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ @@ -1152,12 +1155,15 @@ typedef struct #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ @@ -1179,16 +1185,16 @@ typedef struct #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + /*@}*/ /* end of group CMSIS_TPI */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) @@ -1214,6 +1220,8 @@ typedef struct __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; +#define MPU_TYPE_RALIASES 4U + /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ @@ -1280,10 +1288,9 @@ typedef struct #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ -#endif +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ -#if (__FPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) @@ -1302,6 +1309,7 @@ typedef struct __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ } FPU_Type; /* Floating-Point Context Control Register Definitions */ @@ -1387,8 +1395,12 @@ typedef struct #define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ #define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + /*@} end of group CMSIS_FPU */ -#endif /** @@ -1506,18 +1518,18 @@ typedef struct /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. - \param[in] value Value of register. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ @@ -1529,7 +1541,7 @@ typedef struct @{ */ -/* Memory mapping of Cortex-M4 Hardware */ +/* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ @@ -1548,15 +1560,13 @@ typedef struct #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif -#if (__FPU_PRESENT == 1U) - #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ - #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ -#endif +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ /*@} */ @@ -1584,6 +1594,48 @@ typedef struct @{ */ +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. @@ -1593,7 +1645,7 @@ typedef struct priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ @@ -1602,7 +1654,7 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } @@ -1612,121 +1664,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } /** \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Get Active Interrupt - \details Reads the active register in NVIC and returns the active bit. - \param [in] IRQn Interrupt number. + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { - NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { - return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } @@ -1783,11 +1892,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr } +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ -__STATIC_INLINE void NVIC_SystemReset(void) +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ @@ -1805,6 +1945,50 @@ __STATIC_INLINE void NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + /* ################################## SysTick function ############################################ */ /** @@ -1814,7 +1998,7 @@ __STATIC_INLINE void NVIC_SystemReset(void) @{ */ -#if (__Vendor_SysTickConfig == 0U) +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration @@ -1857,8 +2041,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) @{ */ -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** diff --git a/lib/cmsis/inc/core_cm7.h b/lib/cmsis/inc/core_cm7.h index 3b7530ad505b5..41f9afb64daff 100644 --- a/lib/cmsis/inc/core_cm7.h +++ b/lib/cmsis/inc/core_cm7.h @@ -1,40 +1,30 @@ /**************************************************************************//** * @file core_cm7.h * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 + * @version V5.1.0 + * @date 13. March 2019 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif @@ -70,60 +60,22 @@ @{ */ -/* CMSIS CM7 definitions */ -#define __CM7_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __CM7_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ -#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ - __CM7_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x07U) /*!< Cortex-M Core */ - +#include "cmsis_version.h" -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ -#else - #error Unknown compiler -#endif +#define __CORTEX_M (7U) /*!< Cortex-M Core */ /** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. */ #if defined ( __CC_ARM ) #if defined __TARGET_FPU_VFP - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -133,9 +85,9 @@ #define __FPU_USED 0U #endif -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP - #if (__FPU_PRESENT == 1) +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -147,7 +99,7 @@ #elif defined ( __GNUC__ ) #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -159,7 +111,7 @@ #elif defined ( __ICCARM__ ) #if defined __ARMVFP__ - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -169,9 +121,9 @@ #define __FPU_USED 0U #endif -#elif defined ( __TMS470__ ) +#elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -183,7 +135,7 @@ #elif defined ( __TASKING__ ) #if defined __FPU_VFP__ - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -195,7 +147,7 @@ #elif defined ( __CSMC__ ) #if ( __CSMC__ & 0x400U) - #if (__FPU_PRESENT == 1U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) #define __FPU_USED 1U #else #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" @@ -207,9 +159,8 @@ #endif -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ -#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + #ifdef __cplusplus } @@ -382,11 +333,12 @@ typedef union struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ @@ -412,8 +364,8 @@ typedef union #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ -#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ -#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ @@ -421,6 +373,9 @@ typedef union #define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ #define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ @@ -468,7 +423,7 @@ typedef struct __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ uint32_t RESERVED0[24U]; __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24U]; + uint32_t RESERVED1[24U]; __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ uint32_t RESERVED2[24U]; __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ @@ -529,7 +484,7 @@ typedef struct uint32_t RESERVED4[15U]; __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ - __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ uint32_t RESERVED5[1U]; __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ uint32_t RESERVED6[1U]; @@ -715,6 +670,66 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ @@ -915,6 +930,24 @@ typedef struct #define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ /* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISDYNADD_Pos 26U /*!< ACTLR: DISDYNADD Position */ +#define SCnSCB_ACTLR_DISDYNADD_Msk (1UL << SCnSCB_ACTLR_DISDYNADD_Pos) /*!< ACTLR: DISDYNADD Mask */ + +#define SCnSCB_ACTLR_DISISSCH1_Pos 21U /*!< ACTLR: DISISSCH1 Position */ +#define SCnSCB_ACTLR_DISISSCH1_Msk (0x1FUL << SCnSCB_ACTLR_DISISSCH1_Pos) /*!< ACTLR: DISISSCH1 Mask */ + +#define SCnSCB_ACTLR_DISDI_Pos 16U /*!< ACTLR: DISDI Position */ +#define SCnSCB_ACTLR_DISDI_Msk (0x1FUL << SCnSCB_ACTLR_DISDI_Pos) /*!< ACTLR: DISDI Mask */ + +#define SCnSCB_ACTLR_DISCRITAXIRUR_Pos 15U /*!< ACTLR: DISCRITAXIRUR Position */ +#define SCnSCB_ACTLR_DISCRITAXIRUR_Msk (1UL << SCnSCB_ACTLR_DISCRITAXIRUR_Pos) /*!< ACTLR: DISCRITAXIRUR Mask */ + +#define SCnSCB_ACTLR_DISBTACALLOC_Pos 14U /*!< ACTLR: DISBTACALLOC Position */ +#define SCnSCB_ACTLR_DISBTACALLOC_Msk (1UL << SCnSCB_ACTLR_DISBTACALLOC_Pos) /*!< ACTLR: DISBTACALLOC Mask */ + +#define SCnSCB_ACTLR_DISBTACREAD_Pos 13U /*!< ACTLR: DISBTACREAD Position */ +#define SCnSCB_ACTLR_DISBTACREAD_Msk (1UL << SCnSCB_ACTLR_DISBTACREAD_Pos) /*!< ACTLR: DISBTACREAD Mask */ + #define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ #define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ @@ -1009,10 +1042,7 @@ typedef struct __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ uint32_t RESERVED2[15U]; __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29U]; - __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED3[32U]; uint32_t RESERVED4[43U]; __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ @@ -1033,7 +1063,7 @@ typedef struct /* ITM Trace Privilege Register Definitions */ #define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ /* ITM Trace Control Register Definitions */ #define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ @@ -1063,18 +1093,6 @@ typedef struct #define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ #define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ - /* ITM Lock Status Register Definitions */ #define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ #define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ @@ -1250,7 +1268,7 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ @@ -1261,7 +1279,7 @@ typedef struct __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; @@ -1310,13 +1328,13 @@ typedef struct /* TPI Integration ETM Data Register Definitions (FIFO0) */ #define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ #define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ #define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ #define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ #define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ #define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ @@ -1331,18 +1349,21 @@ typedef struct #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ #define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ #define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ #define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ #define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ #define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ @@ -1357,12 +1378,15 @@ typedef struct #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ @@ -1384,16 +1408,16 @@ typedef struct #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + /*@}*/ /* end of group CMSIS_TPI */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) @@ -1419,6 +1443,8 @@ typedef struct __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ } MPU_Type; +#define MPU_TYPE_RALIASES 4U + /* MPU Type Register Definitions */ #define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ #define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ @@ -1485,10 +1511,9 @@ typedef struct #define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ /*@} end of group CMSIS_MPU */ -#endif +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ -#if (__FPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_FPU Floating Point Unit (FPU) @@ -1595,8 +1620,10 @@ typedef struct /* Media and FP Feature Register 2 Definitions */ +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + /*@} end of group CMSIS_FPU */ -#endif /** @@ -1714,18 +1741,18 @@ typedef struct /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. - \param[in] value Value of register. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ @@ -1737,7 +1764,7 @@ typedef struct @{ */ -/* Memory mapping of Cortex-M4 Hardware */ +/* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ @@ -1756,15 +1783,13 @@ typedef struct #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif -#if (__FPU_PRESENT == 1U) - #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ - #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ -#endif +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ /*@} */ @@ -1792,6 +1817,48 @@ typedef struct @{ */ +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. @@ -1801,7 +1868,7 @@ typedef struct priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ @@ -1810,7 +1877,7 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ reg_value = (reg_value | ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ SCB->AIRCR = reg_value; } @@ -1820,121 +1887,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } /** \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Get Active Interrupt - \details Reads the active register in NVIC and returns the active bit. - \param [in] IRQn Interrupt number. + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { - NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - return(((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { - return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } @@ -1991,11 +2115,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr } +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ -__STATIC_INLINE void NVIC_SystemReset(void) +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ @@ -2013,6 +2168,15 @@ __STATIC_INLINE void NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + /* ########################## FPU functions #################################### */ /** \ingroup CMSIS_Core_FunctionInterface @@ -2034,21 +2198,20 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) uint32_t mvfr0; mvfr0 = SCB->MVFR0; - if ((mvfr0 & 0x00000FF0UL) == 0x220UL) + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) { - return 2UL; /* Double + Single precision FPU */ + return 2U; /* Double + Single precision FPU */ } - else if ((mvfr0 & 0x00000FF0UL) == 0x020UL) + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) { - return 1UL; /* Single precision FPU */ + return 1U; /* Single precision FPU */ } else { - return 0UL; /* No FPU */ + return 0U; /* No FPU */ } } - /*@} end of CMSIS_Core_FpuFunctions */ @@ -2065,17 +2228,22 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void) #define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) #define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) +#define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ /** \brief Enable I-Cache \details Turns on I-Cache */ -__STATIC_INLINE void SCB_EnableICache (void) +__STATIC_FORCEINLINE void SCB_EnableICache (void) { - #if (__ICACHE_PRESENT == 1U) + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */ + __DSB(); __ISB(); SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ __DSB(); __ISB(); @@ -2087,9 +2255,9 @@ __STATIC_INLINE void SCB_EnableICache (void) \brief Disable I-Cache \details Turns off I-Cache */ -__STATIC_INLINE void SCB_DisableICache (void) +__STATIC_FORCEINLINE void SCB_DisableICache (void) { - #if (__ICACHE_PRESENT == 1U) + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) __DSB(); __ISB(); SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ @@ -2104,9 +2272,9 @@ __STATIC_INLINE void SCB_DisableICache (void) \brief Invalidate I-Cache \details Invalidates I-Cache */ -__STATIC_INLINE void SCB_InvalidateICache (void) +__STATIC_FORCEINLINE void SCB_InvalidateICache (void) { - #if (__ICACHE_PRESENT == 1U) + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) __DSB(); __ISB(); SCB->ICIALLU = 0UL; @@ -2120,14 +2288,16 @@ __STATIC_INLINE void SCB_InvalidateICache (void) \brief Enable D-Cache \details Turns on D-Cache */ -__STATIC_INLINE void SCB_EnableDCache (void) +__STATIC_FORCEINLINE void SCB_EnableDCache (void) { - #if (__DCACHE_PRESENT == 1U) + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; - SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */ + + SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; @@ -2142,8 +2312,8 @@ __STATIC_INLINE void SCB_EnableDCache (void) #if defined ( __CC_ARM ) __schedule_barrier(); #endif - } while (ways--); - } while(sets--); + } while (ways-- != 0U); + } while(sets-- != 0U); __DSB(); SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ @@ -2158,19 +2328,20 @@ __STATIC_INLINE void SCB_EnableDCache (void) \brief Disable D-Cache \details Turns off D-Cache */ -__STATIC_INLINE void SCB_DisableDCache (void) +__STATIC_FORCEINLINE void SCB_DisableDCache (void) { - #if (__DCACHE_PRESENT == 1U) + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; - SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); - ccsidr = SCB->CCSIDR; - SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; /* clean & invalidate D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); @@ -2182,8 +2353,8 @@ __STATIC_INLINE void SCB_DisableDCache (void) #if defined ( __CC_ARM ) __schedule_barrier(); #endif - } while (ways--); - } while(sets--); + } while (ways-- != 0U); + } while(sets-- != 0U); __DSB(); __ISB(); @@ -2195,14 +2366,14 @@ __STATIC_INLINE void SCB_DisableDCache (void) \brief Invalidate D-Cache \details Invalidates D-Cache */ -__STATIC_INLINE void SCB_InvalidateDCache (void) +__STATIC_FORCEINLINE void SCB_InvalidateDCache (void) { - #if (__DCACHE_PRESENT == 1U) + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; - SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; @@ -2217,8 +2388,8 @@ __STATIC_INLINE void SCB_InvalidateDCache (void) #if defined ( __CC_ARM ) __schedule_barrier(); #endif - } while (ways--); - } while(sets--); + } while (ways-- != 0U); + } while(sets-- != 0U); __DSB(); __ISB(); @@ -2230,14 +2401,14 @@ __STATIC_INLINE void SCB_InvalidateDCache (void) \brief Clean D-Cache \details Cleans D-Cache */ -__STATIC_INLINE void SCB_CleanDCache (void) +__STATIC_FORCEINLINE void SCB_CleanDCache (void) { - #if (__DCACHE_PRESENT == 1U) + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; - SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; @@ -2252,8 +2423,8 @@ __STATIC_INLINE void SCB_CleanDCache (void) #if defined ( __CC_ARM ) __schedule_barrier(); #endif - } while (ways--); - } while(sets--); + } while (ways-- != 0U); + } while(sets-- != 0U); __DSB(); __ISB(); @@ -2265,14 +2436,14 @@ __STATIC_INLINE void SCB_CleanDCache (void) \brief Clean & Invalidate D-Cache \details Cleans and Invalidates D-Cache */ -__STATIC_INLINE void SCB_CleanInvalidateDCache (void) +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void) { - #if (__DCACHE_PRESENT == 1U) + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; - SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + SCB->CSSELR = 0U; /* select Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; @@ -2287,8 +2458,8 @@ __STATIC_INLINE void SCB_CleanInvalidateDCache (void) #if defined ( __CC_ARM ) __schedule_barrier(); #endif - } while (ways--); - } while(sets--); + } while (ways-- != 0U); + } while(sets-- != 0U); __DSB(); __ISB(); @@ -2298,27 +2469,30 @@ __STATIC_INLINE void SCB_CleanInvalidateDCache (void) /** \brief D-Cache Invalidate by address - \details Invalidates D-Cache for the given address - \param[in] addr address (aligned to 32-byte boundary) + \details Invalidates D-Cache for the given address. + D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address \param[in] dsize size of memory block (in number of bytes) */ -__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize) { - #if (__DCACHE_PRESENT == 1U) - int32_t op_size = dsize; - uint32_t op_addr = (uint32_t)addr; - int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); - __DSB(); + do { + SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); - while (op_size > 0) { - SCB->DCIMVAC = op_addr; - op_addr += linesize; - op_size -= linesize; + __DSB(); + __ISB(); } - - __DSB(); - __ISB(); #endif } @@ -2326,26 +2500,29 @@ __STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize /** \brief D-Cache Clean by address \details Cleans D-Cache for the given address - \param[in] addr address (aligned to 32-byte boundary) + D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned. + \param[in] addr address \param[in] dsize size of memory block (in number of bytes) */ -__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) { - #if (__DCACHE_PRESENT == 1) - int32_t op_size = dsize; - uint32_t op_addr = (uint32_t) addr; - int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); - __DSB(); + do { + SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); - while (op_size > 0) { - SCB->DCCMVAC = op_addr; - op_addr += linesize; - op_size -= linesize; + __DSB(); + __ISB(); } - - __DSB(); - __ISB(); #endif } @@ -2353,30 +2530,32 @@ __STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) /** \brief D-Cache Clean and Invalidate by address \details Cleans and invalidates D_Cache for the given address + D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned and invalidated. \param[in] addr address (aligned to 32-byte boundary) \param[in] dsize size of memory block (in number of bytes) */ -__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) { - #if (__DCACHE_PRESENT == 1U) - int32_t op_size = dsize; - uint32_t op_addr = (uint32_t) addr; - int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); - __DSB(); + do { + SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); - while (op_size > 0) { - SCB->DCCIMVAC = op_addr; - op_addr += linesize; - op_size -= linesize; + __DSB(); + __ISB(); } - - __DSB(); - __ISB(); #endif } - /*@} end of CMSIS_Core_CacheFunctions */ @@ -2389,7 +2568,7 @@ __STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t @{ */ -#if (__Vendor_SysTickConfig == 0U) +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration @@ -2432,8 +2611,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) @{ */ -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** diff --git a/lib/cmsis/inc/core_cmFunc.h b/lib/cmsis/inc/core_cmFunc.h deleted file mode 100644 index 652a48af07a93..0000000000000 --- a/lib/cmsis/inc/core_cmFunc.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************//** - * @file core_cmFunc.h - * @brief CMSIS Cortex-M Core Function Access Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ -#endif - -#ifndef __CORE_CMFUNC_H -#define __CORE_CMFUNC_H - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ -*/ - -/*------------------ RealView Compiler -----------------*/ -#if defined ( __CC_ARM ) - #include "cmsis_armcc.h" - -/*------------------ ARM Compiler V6 -------------------*/ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #include "cmsis_armcc_V6.h" - -/*------------------ GNU Compiler ----------------------*/ -#elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" - -/*------------------ ICC Compiler ----------------------*/ -#elif defined ( __ICCARM__ ) - #include - -/*------------------ TI CCS Compiler -------------------*/ -#elif defined ( __TMS470__ ) - #include - -/*------------------ TASKING Compiler ------------------*/ -#elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -/*------------------ COSMIC Compiler -------------------*/ -#elif defined ( __CSMC__ ) - #include - -#endif - -/*@} end of CMSIS_Core_RegAccFunctions */ - -#endif /* __CORE_CMFUNC_H */ diff --git a/lib/cmsis/inc/core_cmInstr.h b/lib/cmsis/inc/core_cmInstr.h deleted file mode 100644 index f474b0e6f362c..0000000000000 --- a/lib/cmsis/inc/core_cmInstr.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************//** - * @file core_cmInstr.h - * @brief CMSIS Cortex-M Core Instruction Access Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ -#endif - -#ifndef __CORE_CMINSTR_H -#define __CORE_CMINSTR_H - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/*------------------ RealView Compiler -----------------*/ -#if defined ( __CC_ARM ) - #include "cmsis_armcc.h" - -/*------------------ ARM Compiler V6 -------------------*/ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #include "cmsis_armcc_V6.h" - -/*------------------ GNU Compiler ----------------------*/ -#elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" - -/*------------------ ICC Compiler ----------------------*/ -#elif defined ( __ICCARM__ ) - #include - -/*------------------ TI CCS Compiler -------------------*/ -#elif defined ( __TMS470__ ) - #include - -/*------------------ TASKING Compiler ------------------*/ -#elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -/*------------------ COSMIC Compiler -------------------*/ -#elif defined ( __CSMC__ ) - #include - -#endif - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - -#endif /* __CORE_CMINSTR_H */ diff --git a/lib/cmsis/inc/core_cmSimd.h b/lib/cmsis/inc/core_cmSimd.h deleted file mode 100644 index 66bf5c2a725b6..0000000000000 --- a/lib/cmsis/inc/core_cmSimd.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************//** - * @file core_cmSimd.h - * @brief CMSIS Cortex-M SIMD Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang system_header /* treat file as system include file */ -#endif - -#ifndef __CORE_CMSIMD_H -#define __CORE_CMSIMD_H - -#ifdef __cplusplus - extern "C" { -#endif - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -/*------------------ RealView Compiler -----------------*/ -#if defined ( __CC_ARM ) - #include "cmsis_armcc.h" - -/*------------------ ARM Compiler V6 -------------------*/ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #include "cmsis_armcc_V6.h" - -/*------------------ GNU Compiler ----------------------*/ -#elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" - -/*------------------ ICC Compiler ----------------------*/ -#elif defined ( __ICCARM__ ) - #include - -/*------------------ TI CCS Compiler -------------------*/ -#elif defined ( __TMS470__ ) - #include - -/*------------------ TASKING Compiler ------------------*/ -#elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -/*------------------ COSMIC Compiler -------------------*/ -#elif defined ( __CSMC__ ) - #include - -#endif - -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CMSIMD_H */ diff --git a/lib/cmsis/inc/core_sc000.h b/lib/cmsis/inc/core_sc000.h index 514dbd81b9f77..389535a7cf2c1 100644 --- a/lib/cmsis/inc/core_sc000.h +++ b/lib/cmsis/inc/core_sc000.h @@ -1,40 +1,30 @@ /**************************************************************************//** * @file core_sc000.h * @brief CMSIS SC000 Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 + * @version V5.0.6 + * @date 12. November 2018 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif @@ -70,53 +60,15 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS SC000 definitions */ -#define __SC000_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __SC000_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __SC000_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ - __SC000_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_SC (000U) /*!< Cortex secure core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline + __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline - -#else - #error Unknown compiler -#endif +#define __CORTEX_SC (000U) /*!< Cortex secure core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all @@ -128,8 +80,8 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -143,7 +95,7 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined ( __TMS470__ ) +#elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -160,8 +112,8 @@ #endif -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + #ifdef __cplusplus } @@ -569,7 +521,7 @@ typedef struct /*@} end of group CMSIS_SysTick */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) @@ -678,18 +630,18 @@ typedef struct /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. - \param[in] value Value of register. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ @@ -701,7 +653,7 @@ typedef struct @{ */ -/* Memory mapping of SC000 Hardware */ +/* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ @@ -712,7 +664,7 @@ typedef struct #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif @@ -742,7 +694,46 @@ typedef struct @{ */ -/* Interrupt Priorities are WORD accessible only under ARMv6M */ +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else +/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for SC000 */ +/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for SC000 */ + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for SC000 */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ /* The following MACROS handle generation of the register offset and byte masks */ #define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) #define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) @@ -750,79 +741,128 @@ typedef struct /** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } /** \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } else { - NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); } } @@ -830,32 +870,63 @@ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) /** \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } else { - return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); } } +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ -__STATIC_INLINE void NVIC_SystemReset(void) +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ @@ -872,6 +943,31 @@ __STATIC_INLINE void NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + /* ################################## SysTick function ############################################ */ /** @@ -881,7 +977,7 @@ __STATIC_INLINE void NVIC_SystemReset(void) @{ */ -#if (__Vendor_SysTickConfig == 0U) +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration diff --git a/lib/cmsis/inc/core_sc300.h b/lib/cmsis/inc/core_sc300.h index 8bd18aa318a98..5478ea74a5cfb 100644 --- a/lib/cmsis/inc/core_sc300.h +++ b/lib/cmsis/inc/core_sc300.h @@ -1,40 +1,30 @@ /**************************************************************************//** * @file core_sc300.h * @brief CMSIS SC300 Core Peripheral Access Layer Header File - * @version V4.30 - * @date 20. October 2015 + * @version V5.0.7 + * @date 12. November 2018 ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) #pragma clang system_header /* treat file as system include file */ #endif @@ -70,53 +60,15 @@ @{ */ +#include "cmsis_version.h" + /* CMSIS SC300 definitions */ -#define __SC300_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ -#define __SC300_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __SC300_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ #define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ - __SC300_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_SC (300U) /*!< Cortex secure core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline + __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ -#elif defined ( __CSMC__ ) - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ - #define __STATIC_INLINE static inline - -#else - #error Unknown compiler -#endif +#define __CORTEX_SC (300U) /*!< Cortex secure core */ /** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all @@ -128,8 +80,8 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_PCS_VFP +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -143,7 +95,7 @@ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif -#elif defined ( __TMS470__ ) +#elif defined ( __TI_ARM__ ) #if defined __TI_VFP_SUPPORT__ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" #endif @@ -160,8 +112,8 @@ #endif -#include "core_cmInstr.h" /* Core Instruction Access */ -#include "core_cmFunc.h" /* Core Function Access */ +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + #ifdef __cplusplus } @@ -191,7 +143,7 @@ #endif #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 4U + #define __NVIC_PRIO_BITS 3U #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" #endif @@ -308,9 +260,11 @@ typedef union struct { uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ uint32_t C:1; /*!< bit: 29 Carry condition code flag */ @@ -336,12 +290,15 @@ typedef union #define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ #define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ -#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ -#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ #define xPSR_T_Pos 24U /*!< xPSR: T Position */ #define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + #define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ #define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ @@ -599,6 +556,60 @@ typedef struct #define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ #define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + /* SCB Hard Fault Status Register Definitions */ #define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ #define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ @@ -966,7 +977,7 @@ typedef struct */ typedef struct { - __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ uint32_t RESERVED0[2U]; __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ @@ -977,7 +988,7 @@ typedef struct __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ uint32_t RESERVED4[1U]; @@ -1047,8 +1058,11 @@ typedef struct #define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ /* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ /* TPI Integration ITM Data Register Definitions (FIFO1) */ #define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ @@ -1073,12 +1087,15 @@ typedef struct #define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ /* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ /* TPI Integration Mode Control Register Definitions */ #define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ /* TPI DEVID Register Definitions */ #define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ @@ -1100,16 +1117,16 @@ typedef struct #define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ /* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ #define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + /*@}*/ /* end of group CMSIS_TPI */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) /** \ingroup CMSIS_core_register \defgroup CMSIS_MPU Memory Protection Unit (MPU) @@ -1319,18 +1336,18 @@ typedef struct /** \brief Mask and shift a bit field value for use in a register bit range. \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. \return Masked and shifted value. */ -#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) /** \brief Mask and shift a register value to extract a bit filed value. \param[in] field Name of the register bit field. - \param[in] value Value of register. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. \return Masked and shifted bit field value. */ -#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) /*@} end of group CMSIS_core_bitfield */ @@ -1342,7 +1359,7 @@ typedef struct @{ */ -/* Memory mapping of Cortex-M3 Hardware */ +/* Memory mapping of Core Hardware */ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ @@ -1361,7 +1378,7 @@ typedef struct #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ -#if (__MPU_PRESENT == 1U) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ #endif @@ -1392,6 +1409,46 @@ typedef struct @{ */ +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + + /** \brief Set Priority Grouping \details Sets the priority grouping field using the required unlock sequence. @@ -1401,7 +1458,7 @@ typedef struct priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. \param [in] PriorityGroup Priority grouping field. */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ @@ -1420,121 +1477,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) \details Reads the priority grouping field from the NVIC Interrupt Controller. \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) { return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); } /** - \brief Enable External Interrupt - \details Enables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) { - NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** - \brief Disable External Interrupt - \details Disables a device-specific interrupt in the NVIC interrupt controller. - \param [in] IRQn External interrupt number. Value cannot be negative. + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) { - NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } } /** \brief Get Pending Interrupt - \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. - \param [in] IRQn Interrupt number. + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not pending. \return 1 Interrupt status is pending. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Pending Interrupt - \details Sets the pending bit of an external interrupt. - \param [in] IRQn Interrupt number. Value cannot be negative. + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) { - NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Clear Pending Interrupt - \details Clears the pending bit of an external interrupt. - \param [in] IRQn External interrupt number. Value cannot be negative. + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) { - NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } } /** \brief Get Active Interrupt - \details Reads the active register in NVIC and returns the active bit. - \param [in] IRQn Interrupt number. + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. \return 0 Interrupt status is not active. \return 1 Interrupt status is active. + \note IRQn must not be negative. */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) { - return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } } /** \brief Set Interrupt Priority - \details Sets the priority of an interrupt. - \note The priority cannot be set for every core interrupt. + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } else { - NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); } } /** \brief Get Interrupt Priority - \details Reads the priority of an interrupt. - The interrupt number can be positive to specify an external (device specific) interrupt, - or negative to specify an internal (core) interrupt. + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. \param [in] IRQn Interrupt number. \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) { - if ((int32_t)(IRQn) < 0) + if ((int32_t)(IRQn) >= 0) { - return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); } else { - return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); } } @@ -1591,11 +1705,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr } +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + /** \brief System Reset \details Initiates a system reset request to reset the MCU. */ -__STATIC_INLINE void NVIC_SystemReset(void) +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) { __DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */ @@ -1613,6 +1758,31 @@ __STATIC_INLINE void NVIC_SystemReset(void) /*@} end of CMSIS_Core_NVICFunctions */ +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + /* ################################## SysTick function ############################################ */ /** @@ -1622,7 +1792,7 @@ __STATIC_INLINE void NVIC_SystemReset(void) @{ */ -#if (__Vendor_SysTickConfig == 0U) +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) /** \brief System Tick Configuration @@ -1665,8 +1835,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) @{ */ -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ /** diff --git a/lib/cmsis/inc/mpu_armv7.h b/lib/cmsis/inc/mpu_armv7.h new file mode 100644 index 0000000000000..66ef59b4a0bff --- /dev/null +++ b/lib/cmsis/inc/mpu_armv7.h @@ -0,0 +1,272 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.1.0 + * @date 08. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2017-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV7_H +#define ARM_MPU_ARMV7_H + +#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes +#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes +#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes +#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes +#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes +#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte +#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes +#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes +#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes +#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes +#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes +#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes +#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes +#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes +#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes +#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte +#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes +#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes +#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes +#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes +#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes +#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes +#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes +#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes +#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes +#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte +#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes +#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes + +#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access +#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only +#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only +#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access +#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only +#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access + +/** MPU Region Base Address Register Value +* +* \param Region The region to be configured, number 0 to 15. +* \param BaseAddress The base address for the region. +*/ +#define ARM_MPU_RBAR(Region, BaseAddress) \ + (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ + ((Region) & MPU_RBAR_REGION_Msk) | \ + (MPU_RBAR_VALID_Msk)) + +/** +* MPU Memory Access Attributes +* +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +*/ +#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ + ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ + (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ + (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ + (((MPU_RASR_ENABLE_Msk)))) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ + ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) + +/** +* MPU Memory Access Attribute for strongly ordered memory. +* - TEX: 000b +* - Shareable +* - Non-cacheable +* - Non-bufferable +*/ +#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) + +/** +* MPU Memory Access Attribute for device memory. +* - TEX: 000b (if shareable) or 010b (if non-shareable) +* - Shareable or non-shareable +* - Non-cacheable +* - Bufferable (if shareable) or non-bufferable (if non-shareable) +* +* \param IsShareable Configures the device memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) + +/** +* MPU Memory Access Attribute for normal memory. +* - TEX: 1BBb (reflecting outer cacheability rules) +* - Shareable or non-shareable +* - Cacheable or non-cacheable (reflecting inner cacheability rules) +* - Bufferable or non-bufferable (reflecting inner cacheability rules) +* +* \param OuterCp Configures the outer cache policy. +* \param InnerCp Configures the inner cache policy. +* \param IsShareable Configures the memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U)) + +/** +* MPU Memory Access Attribute non-cacheable policy. +*/ +#define ARM_MPU_CACHEP_NOCACHE 0U + +/** +* MPU Memory Access Attribute write-back, write and read allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_WRA 1U + +/** +* MPU Memory Access Attribute write-through, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WT_NWA 2U + +/** +* MPU Memory Access Attribute write-back, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_NWA 3U + + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + MPU->RNR = rnr; + MPU->RASR = 0U; +} + +/** Configure an MPU region. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) +{ + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) +{ + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Memcopy with strictly ordered memory access, e.g. for register targets. +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + while (cnt > MPU_TYPE_RALIASES) { + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif diff --git a/lib/cmsis/inc/mpu_armv8.h b/lib/cmsis/inc/mpu_armv8.h new file mode 100644 index 0000000000000..0041d4dc6ff53 --- /dev/null +++ b/lib/cmsis/inc/mpu_armv8.h @@ -0,0 +1,346 @@ +/****************************************************************************** + * @file mpu_armv8.h + * @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU + * @version V5.1.0 + * @date 08. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2017-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV8_H +#define ARM_MPU_ARMV8_H + +/** \brief Attribute for device memory (outer only) */ +#define ARM_MPU_ATTR_DEVICE ( 0U ) + +/** \brief Attribute for non-cacheable, normal memory */ +#define ARM_MPU_ATTR_NON_CACHEABLE ( 4U ) + +/** \brief Attribute for normal memory (outer and inner) +* \param NT Non-Transient: Set to 1 for non-transient data. +* \param WB Write-Back: Set to 1 to use write-back update policy. +* \param RA Read Allocation: Set to 1 to use cache allocation on read miss. +* \param WA Write Allocation: Set to 1 to use cache allocation on write miss. +*/ +#define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \ + (((NT & 1U) << 3U) | ((WB & 1U) << 2U) | ((RA & 1U) << 1U) | (WA & 1U)) + +/** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGnRnE (0U) + +/** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGnRE (1U) + +/** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGRE (2U) + +/** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_GRE (3U) + +/** \brief Memory Attribute +* \param O Outer memory attributes +* \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes +*/ +#define ARM_MPU_ATTR(O, I) (((O & 0xFU) << 4U) | (((O & 0xFU) != 0U) ? (I & 0xFU) : ((I & 0x3U) << 2U))) + +/** \brief Normal memory non-shareable */ +#define ARM_MPU_SH_NON (0U) + +/** \brief Normal memory outer shareable */ +#define ARM_MPU_SH_OUTER (2U) + +/** \brief Normal memory inner shareable */ +#define ARM_MPU_SH_INNER (3U) + +/** \brief Memory access permissions +* \param RO Read-Only: Set to 1 for read-only memory. +* \param NP Non-Privileged: Set to 1 for non-privileged memory. +*/ +#define ARM_MPU_AP_(RO, NP) (((RO & 1U) << 1U) | (NP & 1U)) + +/** \brief Region Base Address Register value +* \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned. +* \param SH Defines the Shareability domain for this memory region. +* \param RO Read-Only: Set to 1 for a read-only memory region. +* \param NP Non-Privileged: Set to 1 for a non-privileged memory region. +* \oaram XN eXecute Never: Set to 1 for a non-executable memory region. +*/ +#define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \ + ((BASE & MPU_RBAR_BASE_Msk) | \ + ((SH << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \ + ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \ + ((XN << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk)) + +/** \brief Region Limit Address Register value +* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. +* \param IDX The attribute index to be associated with this memory region. +*/ +#define ARM_MPU_RLAR(LIMIT, IDX) \ + ((LIMIT & MPU_RLAR_LIMIT_Msk) | \ + ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ + (MPU_RLAR_EN_Msk)) + +#if defined(MPU_RLAR_PXN_Pos) + +/** \brief Region Limit Address Register with PXN value +* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. +* \param PXN Privileged execute never. Defines whether code can be executed from this privileged region. +* \param IDX The attribute index to be associated with this memory region. +*/ +#define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX) \ + ((LIMIT & MPU_RLAR_LIMIT_Msk) | \ + ((PXN << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk) | \ + ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ + (MPU_RLAR_EN_Msk)) + +#endif + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; /*!< Region Base Address Register value */ + uint32_t RLAR; /*!< Region Limit Address Register value */ +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} + +#ifdef MPU_NS +/** Enable the Non-secure MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control) +{ + MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the Non-secure MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable_NS(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} +#endif + +/** Set the memory attribute encoding to the given MPU. +* \param mpu Pointer to the MPU to be configured. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr) +{ + const uint8_t reg = idx / 4U; + const uint32_t pos = ((idx % 4U) * 8U); + const uint32_t mask = 0xFFU << pos; + + if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) { + return; // invalid index + } + + mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask)); +} + +/** Set the memory attribute encoding. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr) +{ + ARM_MPU_SetMemAttrEx(MPU, idx, attr); +} + +#ifdef MPU_NS +/** Set the memory attribute encoding to the Non-secure MPU. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr) +{ + ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr); +} +#endif + +/** Clear and disable the given MPU region of the given MPU. +* \param mpu Pointer to MPU to be used. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr) +{ + mpu->RNR = rnr; + mpu->RLAR = 0U; +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + ARM_MPU_ClrRegionEx(MPU, rnr); +} + +#ifdef MPU_NS +/** Clear and disable the given Non-secure MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr) +{ + ARM_MPU_ClrRegionEx(MPU_NS, rnr); +} +#endif + +/** Configure the given MPU region of the given MPU. +* \param mpu Pointer to MPU to be used. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + mpu->RNR = rnr; + mpu->RBAR = rbar; + mpu->RLAR = rlar; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar); +} + +#ifdef MPU_NS +/** Configure the given Non-secure MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar); +} +#endif + +/** Memcopy with strictly ordered memory access, e.g. for register targets. +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table to the given MPU. +* \param mpu Pointer to the MPU registers to be used. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + if (cnt == 1U) { + mpu->RNR = rnr; + ARM_MPU_OrderedMemcpy(&(mpu->RBAR), &(table->RBAR), rowWordSize); + } else { + uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U); + uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES; + + mpu->RNR = rnrBase; + while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) { + uint32_t c = MPU_TYPE_RALIASES - rnrOffset; + ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize); + table += c; + cnt -= c; + rnrOffset = 0U; + rnrBase += MPU_TYPE_RALIASES; + mpu->RNR = rnrBase; + } + + ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize); + } +} + +/** Load the given number of MPU regions from a table. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + ARM_MPU_LoadEx(MPU, rnr, table, cnt); +} + +#ifdef MPU_NS +/** Load the given number of MPU regions from a table to the Non-secure MPU. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt); +} +#endif + +#endif + diff --git a/lib/cmsis/inc/tz_context.h b/lib/cmsis/inc/tz_context.h new file mode 100644 index 0000000000000..0d09749f3a506 --- /dev/null +++ b/lib/cmsis/inc/tz_context.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * @file tz_context.h + * @brief Context Management for Armv8-M TrustZone + * @version V1.0.1 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2017-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef TZ_CONTEXT_H +#define TZ_CONTEXT_H + +#include + +#ifndef TZ_MODULEID_T +#define TZ_MODULEID_T +/// \details Data type that identifies secure software modules called by a process. +typedef uint32_t TZ_ModuleId_t; +#endif + +/// \details TZ Memory ID identifies an allocated memory slot. +typedef uint32_t TZ_MemoryId_t; + +/// Initialize secure context memory system +/// \return execution status (1: success, 0: error) +uint32_t TZ_InitContextSystem_S (void); + +/// Allocate context memory for calling secure software modules in TrustZone +/// \param[in] module identifies software modules called from non-secure mode +/// \return value != 0 id TrustZone memory slot identifier +/// \return value 0 no memory available or internal error +TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); + +/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); + +/// Load secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); + +/// Store secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); + +#endif // TZ_CONTEXT_H From 41739506589ec8397613c86d8f682fb7f86c0a9f Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 May 2019 14:37:11 +1000 Subject: [PATCH 0140/1299] mpy-cross: Do not automatically build mpy-cross, rather do it manually. Building mpy-cross automatically leads to some issues with the build process and slows it down. Instead, require it to be built manually. --- README.md | 11 +++++++++++ mpy-cross/Makefile | 17 ----------------- py/mkrules.mk | 6 +----- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 843511a60b79e..aaf310b66285e 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,17 @@ You will also need bash, gcc, and Python 3.3+ available as the command `python3` (if your system only has Python 2.7 then invoke make with the additional option `PYTHON=python2`). +The MicroPython cross-compiler, mpy-cross +----------------------------------------- + +Most ports require the MicroPython cross-compiler to be built first. This +program, called mpy-cross, is used to pre-compile Python scripts to .mpy +files which can then be included (frozen) into the firmware/executable for +a port. To build mpy-cross use: + + $ cd mpy-cross + $ make + The Unix version ---------------- diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index 4ff96fc80c007..2116cc67086e0 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -1,20 +1,3 @@ -# The following is a temporary hack to forefully undefine vars that might have -# be defined by a calling Makefile (from recursive make). -# TODO: Find a better way to be able to call this Makefile recursively. -ifneq ($(findstring undefine,$(.FEATURES)),) -override undefine COPT -override undefine CFLAGS_EXTRA -override undefine LDFLAGS_EXTRA -override undefine MICROPY_FORCE_32BIT -override undefine CROSS_COMPILE -override undefine FROZEN_DIR -override undefine FROZEN_MPY_DIR -override undefine USER_C_MODULES -override undefine SRC_MOD -override undefine BUILD -override undefine PROG -endif - include ../py/mkenv.mk # define main target diff --git a/py/mkrules.mk b/py/mkrules.mk index 4e4fdef55c62d..5c214090cc0c2 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -103,16 +103,12 @@ $(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DE endif ifneq ($(FROZEN_MPY_DIR),) -# to build the MicroPython cross compiler -$(TOP)/mpy-cross/mpy-cross: $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/ports/windows/fmode.c - $(Q)$(MAKE) -C $(TOP)/mpy-cross - # make a list of all the .py files that need compiling and freezing FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)/==') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) # to build .mpy files from .py files -$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py $(TOP)/mpy-cross/mpy-cross +$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py @$(ECHO) "MPY $<" $(Q)$(MKDIR) -p $(dir $@) $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $< From 1043f1a0471757fb46350494aff32114b5e2574b Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 15:58:23 +1000 Subject: [PATCH 0141/1299] lib/netutils: Add DHCP server component. --- lib/netutils/dhcpserver.c | 304 ++++++++++++++++++++++++++++++++++++++ lib/netutils/dhcpserver.h | 49 ++++++ 2 files changed, 353 insertions(+) create mode 100644 lib/netutils/dhcpserver.c create mode 100644 lib/netutils/dhcpserver.h diff --git a/lib/netutils/dhcpserver.c b/lib/netutils/dhcpserver.c new file mode 100644 index 0000000000000..476eb3d69b483 --- /dev/null +++ b/lib/netutils/dhcpserver.c @@ -0,0 +1,304 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// For DHCP specs see: +// https://www.ietf.org/rfc/rfc2131.txt +// https://tools.ietf.org/html/rfc2132 -- DHCP Options and BOOTP Vendor Extensions + +#include +#include +#include "py/mperrno.h" +#include "py/mphal.h" + +#if MICROPY_PY_LWIP + +#include "lib/netutils/dhcpserver.h" +#include "lwip/udp.h" + +#define DHCPDISCOVER (1) +#define DHCPOFFER (2) +#define DHCPREQUEST (3) +#define DHCPDECLINE (4) +#define DHCPACK (5) +#define DHCPNACK (6) +#define DHCPRELEASE (7) +#define DHCPINFORM (8) + +#define DHCP_OPT_PAD (0) +#define DHCP_OPT_SUBNET_MASK (1) +#define DHCP_OPT_ROUTER (3) +#define DHCP_OPT_DNS (6) +#define DHCP_OPT_HOST_NAME (12) +#define DHCP_OPT_REQUESTED_IP (50) +#define DHCP_OPT_IP_LEASE_TIME (51) +#define DHCP_OPT_MSG_TYPE (53) +#define DHCP_OPT_SERVER_ID (54) +#define DHCP_OPT_PARAM_REQUEST_LIST (55) +#define DHCP_OPT_MAX_MSG_SIZE (57) +#define DHCP_OPT_VENDOR_CLASS_ID (60) +#define DHCP_OPT_CLIENT_ID (61) +#define DHCP_OPT_END (255) + +#define PORT_DHCP_SERVER (67) +#define PORT_DHCP_CLIENT (68) + +#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8) +#define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds + +#define MAC_LEN (6) +#define MAKE_IP4(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) + +typedef struct { + uint8_t op; // message opcode + uint8_t htype; // hardware address type + uint8_t hlen; // hardware address length + uint8_t hops; + uint32_t xid; // transaction id, chosen by client + uint16_t secs; // client seconds elapsed + uint16_t flags; + uint8_t ciaddr[4]; // client IP address + uint8_t yiaddr[4]; // your IP address + uint8_t siaddr[4]; // next server IP address + uint8_t giaddr[4]; // relay agent IP address + uint8_t chaddr[16]; // client hardware address + uint8_t sname[64]; // server host name + uint8_t file[128]; // boot file name + uint8_t options[312]; // optional parameters, variable, starts with magic +} dhcp_msg_t; + +static int dhcp_socket_new_dgram(struct udp_pcb **udp, void *cb_data, udp_recv_fn cb_udp_recv) { + // family is AF_INET + // type is SOCK_DGRAM + + *udp = udp_new(); + if (*udp == NULL) { + return -MP_ENOMEM; + } + + // Register callback + udp_recv(*udp, cb_udp_recv, (void*)cb_data); + + return 0; // success +} + +static void dhcp_socket_free(struct udp_pcb **udp) { + if (*udp != NULL) { + udp_remove(*udp); + *udp = NULL; + } +} + +static int dhcp_socket_bind(struct udp_pcb **udp, uint32_t ip, uint16_t port) { + ip_addr_t addr; + IP4_ADDR(&addr, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); + // TODO convert lwIP errors to errno + return udp_bind(*udp, &addr, port); +} + +static int dhcp_socket_sendto(struct udp_pcb **udp, const void *buf, size_t len, uint32_t ip, uint16_t port) { + if (len > 0xffff) { + len = 0xffff; + } + + struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (p == NULL) { + return -MP_ENOMEM; + } + + memcpy(p->payload, buf, len); + + ip_addr_t dest; + IP4_ADDR(&dest, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); + err_t err = udp_sendto(*udp, p, &dest, port); + + pbuf_free(p); + + if (err != ERR_OK) { + return err; + } + + return len; +} + +static uint8_t *opt_find(uint8_t *opt, uint8_t cmd) { + for (int i = 0; i < 308 && opt[i] != DHCP_OPT_END;) { + if (opt[i] == cmd) { + return &opt[i]; + } + i += 2 + opt[i + 1]; + } + return NULL; +} + +static void opt_write_n(uint8_t **opt, uint8_t cmd, size_t n, void *data) { + uint8_t *o = *opt; + *o++ = cmd; + *o++ = n; + memcpy(o, data, n); + *opt = o + n; +} + +static void opt_write_u8(uint8_t **opt, uint8_t cmd, uint8_t val) { + uint8_t *o = *opt; + *o++ = cmd; + *o++ = 1; + *o++ = val; + *opt = o; +} + +static void opt_write_u32(uint8_t **opt, uint8_t cmd, uint32_t val) { + uint8_t *o = *opt; + *o++ = cmd; + *o++ = 4; + *o++ = val >> 24; + *o++ = val >> 16; + *o++ = val >> 8; + *o++ = val; + *opt = o; +} + +static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *src_addr, u16_t src_port) { + dhcp_server_t *d = arg; + (void)upcb; + (void)src_addr; + (void)src_port; + + // This is around 548 bytes + dhcp_msg_t dhcp_msg; + + #define DHCP_MIN_SIZE (240 + 3) + if (p->tot_len < DHCP_MIN_SIZE) { + goto ignore_request; + } + + size_t len = pbuf_copy_partial(p, &dhcp_msg, sizeof(dhcp_msg), 0); + if (len < DHCP_MIN_SIZE) { + goto ignore_request; + } + + dhcp_msg.op = DHCPOFFER; + memcpy(&dhcp_msg.yiaddr, &d->ip.addr, 4); + + uint8_t *opt = (uint8_t*)&dhcp_msg.options; + opt += 4; // assume magic cookie: 99, 130, 83, 99 + + switch (opt[2]) { + case DHCPDISCOVER: { + int yi = DHCPS_MAX_IP; + for (int i = 0; i < DHCPS_MAX_IP; ++i) { + if (memcmp(d->lease[i].mac, dhcp_msg.chaddr, MAC_LEN) == 0) { + // MAC match, use this IP address + yi = i; + break; + } + if (yi == DHCPS_MAX_IP) { + // Look for a free IP address + if (memcmp(d->lease[i].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) { + // IP available + yi = i; + } + uint32_t expiry = d->lease[i].expiry << 16 | 0xffff; + if ((int32_t)(expiry - mp_hal_ticks_ms()) < 0) { + // IP expired, reuse it + memset(d->lease[i].mac, 0, MAC_LEN); + yi = i; + } + } + } + if (yi == DHCPS_MAX_IP) { + // No more IP addresses left + goto ignore_request; + } + dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi; + opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPOFFER); + break; + } + + case DHCPREQUEST: { + uint8_t *o = opt_find(opt, DHCP_OPT_REQUESTED_IP); + if (o == NULL) { + // Should be NACK + goto ignore_request; + } + if (memcmp(o + 2, &d->ip.addr, 3) != 0) { + // Should be NACK + goto ignore_request; + } + uint8_t yi = o[5] - DHCPS_BASE_IP; + if (yi >= DHCPS_MAX_IP) { + // Should be NACK + goto ignore_request; + } + if (memcmp(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN) == 0) { + // MAC match, ok to use this IP address + } else if (memcmp(d->lease[yi].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) { + // IP unused, ok to use this IP address + memcpy(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN); + } else { + // IP already in use + // Should be NACK + goto ignore_request; + } + d->lease[yi].expiry = (mp_hal_ticks_ms() + DEFAULT_LEASE_TIME_S * 1000) >> 16; + dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi; + opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPACK); + printf("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n", + dhcp_msg.chaddr[0], dhcp_msg.chaddr[1], dhcp_msg.chaddr[2], dhcp_msg.chaddr[3], dhcp_msg.chaddr[4], dhcp_msg.chaddr[5], + dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3]); + break; + } + + default: + goto ignore_request; + } + + opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, &d->ip.addr); + opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, &d->nm.addr); + opt_write_n(&opt, DHCP_OPT_ROUTER, 4, &d->ip.addr); // aka gateway; can have mulitple addresses + opt_write_u32(&opt, DHCP_OPT_DNS, DEFAULT_DNS); // can have mulitple addresses + opt_write_u32(&opt, DHCP_OPT_IP_LEASE_TIME, DEFAULT_LEASE_TIME_S); + *opt++ = DHCP_OPT_END; + dhcp_socket_sendto(&d->udp, &dhcp_msg, opt - (uint8_t*)&dhcp_msg, 0xffffffff, PORT_DHCP_CLIENT); + +ignore_request: + pbuf_free(p); +} + +void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm) { + ip_addr_copy(d->ip, *ip); + ip_addr_copy(d->nm, *nm); + memset(d->lease, 0, sizeof(d->lease)); + if (dhcp_socket_new_dgram(&d->udp, d, dhcp_server_process) != 0) { + return; + } + dhcp_socket_bind(&d->udp, 0, PORT_DHCP_SERVER); +} + +void dhcp_server_deinit(dhcp_server_t *d) { + dhcp_socket_free(&d->udp); +} + +#endif // MICROPY_PY_LWIP diff --git a/lib/netutils/dhcpserver.h b/lib/netutils/dhcpserver.h new file mode 100644 index 0000000000000..2349d2ea427f4 --- /dev/null +++ b/lib/netutils/dhcpserver.h @@ -0,0 +1,49 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H +#define MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H + +#include "lwip/ip_addr.h" + +#define DHCPS_BASE_IP (16) +#define DHCPS_MAX_IP (8) + +typedef struct _dhcp_server_lease_t { + uint8_t mac[6]; + uint16_t expiry; +} dhcp_server_lease_t; + +typedef struct _dhcp_server_t { + ip_addr_t ip; + ip_addr_t nm; + dhcp_server_lease_t lease[DHCPS_MAX_IP]; + struct udp_pcb *udp; +} dhcp_server_t; + +void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm); +void dhcp_server_deinit(dhcp_server_t *d); + +#endif // MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H From 53f2ac9017e616975194b509dd1b29c4a30cfb1d Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 15:59:48 +1000 Subject: [PATCH 0142/1299] gitattributes: Mark *.a files as binary. --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index fdd31021f72c8..e6d31d6aa31fc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,7 @@ *.bat text eol=crlf # These are binary so should never be modified by git. +*.a binary *.png binary *.jpg binary *.dxf binary From 7b70ab7258986567dd970d5108cd45c706b36a96 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:00:56 +1000 Subject: [PATCH 0143/1299] drivers: Add driver for CYW43xx WiFi SoCs. --- drivers/cyw43/README.md | 17 ++ drivers/cyw43/cyw43.h | 135 +++++++++ drivers/cyw43/cyw43_ctrl.c | 588 +++++++++++++++++++++++++++++++++++++ drivers/cyw43/cyw43_ll.h | 135 +++++++++ drivers/cyw43/cyw43_lwip.c | 197 +++++++++++++ drivers/cyw43/libcyw43.a | Bin 0 -> 437538 bytes 6 files changed, 1072 insertions(+) create mode 100644 drivers/cyw43/README.md create mode 100644 drivers/cyw43/cyw43.h create mode 100644 drivers/cyw43/cyw43_ctrl.c create mode 100644 drivers/cyw43/cyw43_ll.h create mode 100644 drivers/cyw43/cyw43_lwip.c create mode 100644 drivers/cyw43/libcyw43.a diff --git a/drivers/cyw43/README.md b/drivers/cyw43/README.md new file mode 100644 index 0000000000000..5af6f65580668 --- /dev/null +++ b/drivers/cyw43/README.md @@ -0,0 +1,17 @@ +CYW43xx WiFi SoC driver +======================= + +This is a driver for the CYW43xx WiFi SoC. + +There are four layers to the driver: + +1. SDIO bus interface, provided by the host device/system. + +2. Low-level CYW43xx interface, managing the bus, control messages, Ethernet + frames and asynchronous events. Includes download of SoC firmware. The + header file `cyw43_ll.h` defines the interface to this layer. + +3. Mid-level CYW43xx control, to control and set WiFi parameters and manage + events. See `cyw43_ctrl.c`. + +4. TCP/IP bindings to lwIP. See `cyw43_lwip.c`. diff --git a/drivers/cyw43/cyw43.h b/drivers/cyw43/cyw43.h new file mode 100644 index 0000000000000..d7f08cb5dfeed --- /dev/null +++ b/drivers/cyw43/cyw43.h @@ -0,0 +1,135 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_CYW43_H +#define MICROPY_INCLUDED_STM32_CYW43_H + +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lib/netutils/dhcpserver.h" +#include "drivers/cyw43/cyw43_ll.h" + +// For trace_flags +#define CYW43_TRACE_ASYNC_EV (0x0001) +#define CYW43_TRACE_ETH_TX (0x0002) +#define CYW43_TRACE_ETH_RX (0x0004) +#define CYW43_TRACE_ETH_FULL (0x0008) +#define CYW43_TRACE_MAC (0x0010) + +// Return value of cyw43_wifi_link_status +#define CYW43_LINK_DOWN (0) +#define CYW43_LINK_JOIN (1) +#define CYW43_LINK_NOIP (2) +#define CYW43_LINK_UP (3) +#define CYW43_LINK_FAIL (-1) +#define CYW43_LINK_NONET (-2) +#define CYW43_LINK_BADAUTH (-3) + +typedef struct _cyw43_t { + cyw43_ll_t cyw43_ll; + + uint8_t itf_state; + uint32_t trace_flags; + + // State for async events + volatile uint32_t wifi_scan_state; + uint32_t wifi_join_state; + void *wifi_scan_env; + int (*wifi_scan_cb)(void*, const cyw43_ev_scan_result_t*); + + // Pending things to do + bool pend_disassoc; + bool pend_rejoin; + bool pend_rejoin_wpa; + + // AP settings + uint8_t ap_channel; + uint8_t ap_auth; + uint8_t ap_ssid_len; + uint8_t ap_key_len; + uint8_t ap_ssid[32]; + uint8_t ap_key[64]; + + // lwIP data + struct netif netif[2]; + struct dhcp dhcp_client; + dhcp_server_t dhcp_server; +} cyw43_t; + +extern cyw43_t cyw43_state; +extern void (*cyw43_poll)(void); +extern uint32_t cyw43_sleep; + +void cyw43_init(cyw43_t *self); +void cyw43_deinit(cyw43_t *self); + +int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface); +int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf); + +int cyw43_wifi_pm(cyw43_t *self, uint32_t pm); +int cyw43_wifi_link_status(cyw43_t *self, int itf); +void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up); +int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]); +int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)); + +static inline bool cyw43_wifi_scan_active(cyw43_t *self) { + return self->wifi_scan_state == 1; +} + +int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel); +int cyw43_wifi_leave(cyw43_t *self, int itf); + +static inline void cyw43_wifi_ap_get_ssid(cyw43_t *self, size_t *len, const uint8_t **buf) { + *len = self->ap_ssid_len; + *buf = self->ap_ssid; +} + +static inline void cyw43_wifi_ap_set_channel(cyw43_t *self, uint32_t channel) { + self->ap_channel = channel; +} + +static inline void cyw43_wifi_ap_set_ssid(cyw43_t *self, size_t len, const uint8_t *buf) { + self->ap_ssid_len = MIN(len, sizeof(self->ap_ssid)); + memcpy(self->ap_ssid, buf, self->ap_ssid_len); +} + +static inline void cyw43_wifi_ap_set_password(cyw43_t *self, size_t len, const uint8_t *buf) { + self->ap_key_len = MIN(len, sizeof(self->ap_key)); + memcpy(self->ap_key, buf, self->ap_key_len); +} + +static inline void cyw43_wifi_ap_set_auth(cyw43_t *self, uint32_t auth) { + self->ap_auth = auth; +} + +void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs); + +void cyw43_tcpip_init(cyw43_t *self, int itf); +void cyw43_tcpip_deinit(cyw43_t *self, int itf); +void cyw43_tcpip_set_link_up(cyw43_t *self, int itf); +void cyw43_tcpip_set_link_down(cyw43_t *self, int itf); +int cyw43_tcpip_link_status(cyw43_t *self, int itf); + +#endif // MICROPY_INCLUDED_STM32_CYW43_H diff --git a/drivers/cyw43/cyw43_ctrl.c b/drivers/cyw43/cyw43_ctrl.c new file mode 100644 index 0000000000000..3a8bbf8646f40 --- /dev/null +++ b/drivers/cyw43/cyw43_ctrl.c @@ -0,0 +1,588 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/mphal.h" +#include "drivers/cyw43/cyw43.h" +#include "pendsv.h" +#include "sdio.h" + +#define CYW_ENTER MICROPY_PY_LWIP_ENTER +#define CYW_EXIT MICROPY_PY_LWIP_EXIT + +#ifdef pyb_pin_WL_HOST_WAKE +#define USE_SDIOIT (0) +#else +#define USE_SDIOIT (1) +#endif + +#define CYW43_SLEEP_MAX (50) + +#define WIFI_JOIN_STATE_ACTIVE (0x0001) +#define WIFI_JOIN_STATE_FAIL (0x0002) +#define WIFI_JOIN_STATE_NONET (0x0003) +#define WIFI_JOIN_STATE_BADAUTH (0x0004) +#define WIFI_JOIN_STATE_AUTH (0x0200) +#define WIFI_JOIN_STATE_LINK (0x0400) +#define WIFI_JOIN_STATE_KEYED (0x0800) +#define WIFI_JOIN_STATE_ALL (0x0e01) + +cyw43_t cyw43_state; +void (*cyw43_poll)(void); +uint32_t cyw43_sleep; + +STATIC void cyw43_poll_func(void); +STATIC void cyw43_wifi_ap_init(cyw43_t *self); +STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up); + +static inline uint32_t cyw43_get_be16(const uint8_t *buf) { + return buf[0] << 8 | buf[1]; +} + +static inline uint32_t cyw43_get_be32(const uint8_t *buf) { + return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; +} + +static inline void cyw43_delay_ms(uint32_t ms) { + mp_hal_delay_ms(ms); +} + +/*******************************************************************************/ +// Initialisation and polling + +void cyw43_init(cyw43_t *self) { + #ifdef pyb_pin_WL_HOST_WAKE + mp_hal_pin_config(pyb_pin_WL_HOST_WAKE, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); + #endif + mp_hal_pin_config(pyb_pin_WL_REG_ON, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_low(pyb_pin_WL_REG_ON); + #ifdef pyb_pin_WL_RFSW_VDD + mp_hal_pin_config(pyb_pin_WL_RFSW_VDD, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power + mp_hal_pin_low(pyb_pin_WL_RFSW_VDD); + #endif + + cyw43_ll_init(&self->cyw43_ll, self); + + self->itf_state = 0; + self->wifi_scan_state = 0; + self->wifi_join_state = 0; + self->pend_disassoc = false; + self->pend_rejoin= false; + self->pend_rejoin_wpa = false; + self->ap_channel = 3; + self->ap_ssid_len = 0; + self->ap_key_len = 0; + + cyw43_poll = NULL; +} + +void cyw43_deinit(cyw43_t *self) { + CYW_ENTER + + cyw43_ll_bus_sleep(&self->cyw43_ll, true); + cyw43_delay_ms(2); + cyw43_tcpip_deinit(self, 0); + cyw43_tcpip_deinit(self, 1); + + self->itf_state = 0; + + // Disable async polling + SDMMC1->MASK &= ~SDMMC_MASK_SDIOITIE; + cyw43_poll = NULL; + + #ifdef pyb_pin_WL_RFSW_VDD + // Turn the RF-switch off + mp_hal_pin_low(pyb_pin_WL_RFSW_VDD); + #endif + + // Power down the WL chip and the SDIO bus + mp_hal_pin_low(pyb_pin_WL_REG_ON); + sdio_deinit(); + + CYW_EXIT +} + +STATIC int cyw43_ensure_up(cyw43_t *self) { + if (cyw43_poll != NULL) { + cyw43_ll_bus_sleep(&self->cyw43_ll, false); + return 0; + } + + CYW_ENTER + + // Disable the netif if it was previously up + cyw43_tcpip_deinit(self, CYW43_ITF_STA); + cyw43_tcpip_deinit(self, CYW43_ITF_AP); + self->itf_state = 0; + + // Reset and power up the WL chip + mp_hal_pin_low(pyb_pin_WL_REG_ON); + cyw43_delay_ms(20); + mp_hal_pin_high(pyb_pin_WL_REG_ON); + cyw43_delay_ms(50); + + // Initialise SDIO bus + // IRQ priority only needs to be higher than CYW_ENTER/EXIT protection (PENDSV) + sdio_init(NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0)); + + // Initialise the low-level driver + uint8_t mac[6]; + mp_hal_get_mac(MP_HAL_MAC_WLAN0, mac); + int ret = cyw43_ll_bus_init(&self->cyw43_ll, mac); + + if (ret != 0) { + CYW_EXIT + return ret; + } + + // Enable async events from low-level driver + cyw43_sleep = CYW43_SLEEP_MAX; + cyw43_poll = cyw43_poll_func; + #if USE_SDIOIT + SDMMC1->MASK |= SDMMC_MASK_SDIOITIE; + #else + extern void extint_set(const pin_obj_t *pin, uint32_t mode); + extint_set(pyb_pin_WL_HOST_WAKE, GPIO_MODE_IT_FALLING); + #endif + + CYW_EXIT + + return ret; +} + +// This function must always be executed at the level where CYW_ENTER is effectively active +STATIC void cyw43_poll_func(void) { + if (cyw43_poll == NULL) { + // Poll scheduled during deinit, just ignore it + return; + } + + cyw43_t *self = &cyw43_state; + cyw43_ll_process_packets(&self->cyw43_ll); + + if (self->pend_disassoc) { + self->pend_disassoc = false; + cyw43_ll_ioctl(&self->cyw43_ll, CYW43_IOCTL_SET_DISASSOC, 0, NULL, CYW43_ITF_STA); + } + + if (self->pend_rejoin_wpa) { + self->pend_rejoin_wpa = false; + cyw43_ll_wifi_set_wpa_auth(&self->cyw43_ll); + } + + if (self->pend_rejoin) { + self->pend_rejoin = false; + cyw43_ll_wifi_rejoin(&self->cyw43_ll); + self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; + } + + if (cyw43_sleep == 0) { + cyw43_ll_bus_sleep(&self->cyw43_ll, true); + #if !USE_SDIOIT + sdio_deinit(); // save power while WLAN bus sleeps + #endif + } + + #if USE_SDIOIT + SDMMC1->MASK |= SDMMC_MASK_SDIOITIE; + #endif +} + +/*******************************************************************************/ +// Callback interface to low-level driver + +int cyw43_cb_read_host_interrupt_pin(void *cb_data) { + #ifdef pyb_pin_WL_HOST_WAKE + return mp_hal_pin_read(pyb_pin_WL_HOST_WAKE); + #else + return mp_hal_pin_read(pyb_pin_WL_SDIO_1); + #endif +} + +void cyw43_cb_ensure_awake(void *cb_data) { + cyw43_sleep = CYW43_SLEEP_MAX; + #if !USE_SDIOIT + if (__HAL_RCC_SDMMC1_IS_CLK_DISABLED()) { + __HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral + sdio_enable_high_speed_4bit(); + } + #endif +} + +STATIC const char *cyw43_async_event_name_table[89] = { + [0 ... 88] = NULL, + [CYW43_EV_SET_SSID] = "SET_SSID", + [CYW43_EV_JOIN] = "JOIN", + [CYW43_EV_AUTH] = "AUTH", + [CYW43_EV_DEAUTH_IND] = "DEAUTH_IND", + [CYW43_EV_ASSOC] = "ASSOC", + [CYW43_EV_DISASSOC] = "DISASSOC", + [CYW43_EV_DISASSOC_IND] = "DISASSOC_IND", + [CYW43_EV_LINK] = "LINK", + [CYW43_EV_PSK_SUP] = "PSK_SUP", + [CYW43_EV_ESCAN_RESULT] = "ESCAN_RESULT", + [CYW43_EV_CSA_COMPLETE_IND] = "CSA_COMPLETE_IND", + [CYW43_EV_ASSOC_REQ_IE] = "ASSOC_REQ_IE", + [CYW43_EV_ASSOC_RESP_IE] = "ASSOC_RESP_IE", +}; + +STATIC void cyw43_dump_async_event(const cyw43_async_event_t *ev) { + printf("[% 8d] ASYNC(%04x,", + mp_hal_ticks_ms(), + (unsigned int)ev->flags + ); + if (ev->event_type < MP_ARRAY_SIZE(cyw43_async_event_name_table) + && cyw43_async_event_name_table[ev->event_type] != NULL) { + printf("%s", cyw43_async_event_name_table[ev->event_type]); + } else { + printf("%u", (unsigned int)ev->event_type); + } + printf(",%u,%u,%u)\n", + (unsigned int)ev->status, + (unsigned int)ev->reason, + (unsigned int)ev->interface + ); +} + +void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev) { + cyw43_t *self = cb_data; + + if (self->trace_flags & CYW43_TRACE_ASYNC_EV) { + cyw43_dump_async_event(ev); + } + + if (ev->event_type == CYW43_EV_ESCAN_RESULT && self->wifi_scan_state == 1) { + // Escan result event + if (ev->status == 8) { + // Partial result + int ret = self->wifi_scan_cb(self->wifi_scan_env, &ev->u.scan_result); + if (ret != 0) { + // TODO need to abort scan, or just ignore any more results + } + } else if (ev->status == 0) { + // Scan complete + self->wifi_scan_state = 2; + } + + } else if (ev->event_type == CYW43_EV_DISASSOC) { + cyw43_tcpip_set_link_down(self, CYW43_ITF_STA); + self->wifi_join_state = 0x0000; + + /* + } else if (ev->event_type == CYW43_EV_DISASSOC_IND) { + if (ev->interface == CYW43_ITF_AP) { + // Station disassociated with our AP, let DHCP server know so it can free the IP address + dhcp_server_disassoc(&self->dhcp_server, buf + 24); + } + */ + + // WiFi join events + } else if (ev->event_type == CYW43_EV_PRUNE) { + if (ev->status == 0 && ev->reason == 8) { + // RSN mismatch, retry join with WPA auth + self->pend_rejoin = true; + self->pend_rejoin_wpa = true; + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); + } + } else if (ev->event_type == CYW43_EV_SET_SSID) { + if (ev->status == 0) { + // Success setting SSID + } else if (ev->status == 3 && ev->reason == 0) { + self->wifi_join_state = WIFI_JOIN_STATE_NONET; + // No matching SSID found (could be out of range, or down) + } else { + // Other failure setting SSID + self->wifi_join_state = WIFI_JOIN_STATE_FAIL; + } + } else if (ev->event_type == CYW43_EV_AUTH) { + if (ev->status == 0) { + self->wifi_join_state |= WIFI_JOIN_STATE_AUTH; + } else if (ev->status == 6) { + // Unsolicited auth packet, ignore it + } else { + // Cannot authenticate + self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH; + } + } else if (ev->event_type == CYW43_EV_DEAUTH_IND) { + if (ev->status == 0 && ev->reason == 2) { + // Deauth, probably because password was wrong; disassociate + self->pend_disassoc = true; + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); + } + } else if (ev->event_type == CYW43_EV_LINK) { + if (ev->status == 0) { + if (ev->flags & 1) { + // Link is up + if (ev->interface == CYW43_ITF_STA) { + self->wifi_join_state |= WIFI_JOIN_STATE_LINK; + } else { + cyw43_tcpip_set_link_up(self, ev->interface); + } + } else { + // Link is down + cyw43_tcpip_set_link_down(self, ev->interface); + } + } + } else if (ev->event_type == CYW43_EV_PSK_SUP) { + if (ev->status == 6) { // WLC_SUP_KEYED + self->wifi_join_state |= WIFI_JOIN_STATE_KEYED; + } else if ((ev->status == 4 || ev->status == 8 || ev->status == 11) && ev->reason == 15) { + // Timeout waiting for key exchange M1/M3/G1 + // Probably at edge of the cell, retry + self->pend_rejoin = true; + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func); + } else { + // PSK_SUP failure + self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH; + } + } + + if (self->wifi_join_state == WIFI_JOIN_STATE_ALL) { + // STA connected + self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; + cyw43_tcpip_set_link_up(self, CYW43_ITF_STA); + } +} + +/*******************************************************************************/ +// Ioctl and Ethernet interface + +int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) { + int ret = cyw43_ensure_up(self); + if (ret) { + return ret; + } + + CYW_ENTER + ret = cyw43_ll_ioctl(&self->cyw43_ll, cmd, len, buf, iface); + CYW_EXIT + + return ret; +} + +int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf) { + int ret = cyw43_ensure_up(self); + if (ret) { + return ret; + } + + CYW_ENTER + ret = cyw43_ll_send_ethernet(&self->cyw43_ll, itf, len, buf, is_pbuf); + CYW_EXIT + + return ret; +} + +/*******************************************************************************/ +// WiFi control + +STATIC int cyw43_wifi_on(cyw43_t *self, uint32_t country) { + int ret = cyw43_ensure_up(self); + if (ret) { + return ret; + } + + #ifdef pyb_pin_WL_RFSW_VDD + // Turn the RF-switch on + mp_hal_pin_high(pyb_pin_WL_RFSW_VDD); + #endif + + CYW_ENTER + ret = cyw43_ll_wifi_on(&self->cyw43_ll, country); + CYW_EXIT + + return ret; +} + +int cyw43_wifi_pm(cyw43_t *self, uint32_t pm_in) { + int ret = cyw43_ensure_up(self); + if (ret) { + return ret; + } + + // pm_in: 0x00adbrrm + uint32_t pm = pm_in & 0xf; + uint32_t pm_sleep_ret = (pm_in >> 4) & 0xff; + uint32_t li_bcn = (pm_in >> 12) & 0xf; + uint32_t li_dtim = (pm_in >> 16) & 0xf; + uint32_t li_assoc = (pm_in >> 20) & 0xf; + + CYW_ENTER + ret = cyw43_ll_wifi_pm(&self->cyw43_ll, pm, pm_sleep_ret, li_bcn, li_dtim, li_assoc); + CYW_EXIT + + return ret; +} + +int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]) { + mp_hal_get_mac(MP_HAL_MAC_WLAN0, &mac[0]); + return 0; +} + +#define MAKE_COUNTRY(a, b, rev) ((a) | (b) << 8 | (rev) << 16) + +void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up) { + if (up) { + if (self->itf_state == 0) { + uint32_t country; + extern char pyb_country_code[2]; + if (pyb_country_code[0] == '\0' || pyb_country_code[1] == '\0') { + country = MAKE_COUNTRY('X', 'X', 17); // default to world-wide (passive ch 12-14) + } else { + country = MAKE_COUNTRY(pyb_country_code[0], pyb_country_code[1], 0); + } + cyw43_wifi_on(self, country); + cyw43_wifi_pm(self, 10 << 20 | 1 << 16 | 1 << 12 | 20 << 4 | 2); + } + if (itf == CYW43_ITF_AP) { + cyw43_wifi_ap_init(self); + cyw43_wifi_ap_set_up(self, true); + } + if ((self->itf_state & (1 << itf)) == 0) { + CYW_ENTER + cyw43_tcpip_deinit(self, itf); + cyw43_tcpip_init(self, itf); + self->itf_state |= 1 << itf; + CYW_EXIT + } + } else { + if (itf == CYW43_ITF_AP) { + cyw43_wifi_ap_set_up(self, false); + } + } +} + +int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)) { + if (self->itf_state == 0) { + return -1; + } + + cyw43_ensure_up(self); + + CYW_ENTER + + // Set state and callback data + self->wifi_scan_state = 1; + self->wifi_scan_env = env; + self->wifi_scan_cb = result_cb; + + // Start the scan + int ret = cyw43_ll_wifi_scan(&self->cyw43_ll, opts); + + CYW_EXIT + + return ret; +} + +int cyw43_wifi_link_status(cyw43_t *self, int itf) { + if (itf == CYW43_ITF_STA) { + int s = self->wifi_join_state & 0xf; + if (s == WIFI_JOIN_STATE_ACTIVE) { + return CYW43_LINK_JOIN; + } else if (s == WIFI_JOIN_STATE_FAIL) { + return CYW43_LINK_FAIL; + } else if (s == WIFI_JOIN_STATE_NONET) { + return CYW43_LINK_NONET; + } else if (s == WIFI_JOIN_STATE_BADAUTH) { + return CYW43_LINK_BADAUTH; + } else { + return CYW43_LINK_DOWN; + } + } else { + return CYW43_LINK_DOWN; + } +} + +/*******************************************************************************/ +// WiFi STA + +int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel) { + int ret = cyw43_ensure_up(self); + if (ret) { + return ret; + } + + CYW_ENTER + + ret = cyw43_ll_wifi_join(&self->cyw43_ll, ssid_len, ssid, key_len, key, auth_type, bssid, channel); + + if (ret == 0) { + // Wait for responses: EV_AUTH, EV_LINK, EV_SET_SSID, EV_PSK_SUP + // Will get EV_DEAUTH_IND if password is invalid + self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE; + + if (auth_type == 0) { + // For open security we don't need EV_PSK_SUP, so set that flag indicator now + self->wifi_join_state |= WIFI_JOIN_STATE_KEYED; + } + } + + CYW_EXIT + + return ret; +} + +int cyw43_wifi_leave(cyw43_t *self, int itf) { + // Disassociate with SSID + return cyw43_ioctl(self, CYW43_IOCTL_SET_DISASSOC, 0, NULL, itf); +} + +/*******************************************************************************/ +// WiFi AP + +STATIC void cyw43_wifi_ap_init(cyw43_t *self) { + int ret = cyw43_ensure_up(self); + if (ret) { + return; + } + + CYW_ENTER + cyw43_ll_wifi_ap_init(&self->cyw43_ll, self->ap_ssid_len, self->ap_ssid, self->ap_auth, self->ap_key_len, self->ap_key, self->ap_channel); + CYW_EXIT +} + +STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up) { + int ret = cyw43_ensure_up(self); + if (ret) { + return; + } + + CYW_ENTER + cyw43_ll_wifi_ap_set_up(&self->cyw43_ll, up); + CYW_EXIT +} + +void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs) { + int ret = cyw43_ensure_up(self); + if (ret) { + return; + } + + CYW_ENTER + cyw43_ll_wifi_ap_get_stas(&self->cyw43_ll, num_stas, macs); + CYW_EXIT +} diff --git a/drivers/cyw43/cyw43_ll.h b/drivers/cyw43/cyw43_ll.h new file mode 100644 index 0000000000000..879367a2edd9e --- /dev/null +++ b/drivers/cyw43/cyw43_ll.h @@ -0,0 +1,135 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_CYW43_LL_H +#define MICROPY_INCLUDED_STM32_CYW43_LL_H + +// IOCTL commands +#define CYW43_IOCTL_GET_SSID (0x32) +#define CYW43_IOCTL_GET_CHANNEL (0x3a) +#define CYW43_IOCTL_SET_DISASSOC (0x69) +#define CYW43_IOCTL_GET_ANTDIV (0x7e) +#define CYW43_IOCTL_SET_ANTDIV (0x81) +#define CYW43_IOCTL_SET_MONITOR (0xd9) +#define CYW43_IOCTL_GET_VAR (0x20c) +#define CYW43_IOCTL_SET_VAR (0x20f) + +// Async events, event_type field +#define CYW43_EV_SET_SSID (0) +#define CYW43_EV_JOIN (1) +#define CYW43_EV_AUTH (3) +#define CYW43_EV_DEAUTH_IND (6) +#define CYW43_EV_ASSOC (7) +#define CYW43_EV_DISASSOC (11) +#define CYW43_EV_DISASSOC_IND (12) +#define CYW43_EV_LINK (16) +#define CYW43_EV_PRUNE (23) +#define CYW43_EV_PSK_SUP (46) +#define CYW43_EV_ESCAN_RESULT (69) +#define CYW43_EV_CSA_COMPLETE_IND (80) +#define CYW43_EV_ASSOC_REQ_IE (87) +#define CYW43_EV_ASSOC_RESP_IE (88) + +enum { + CYW43_ITF_STA, + CYW43_ITF_AP, +}; + +typedef struct _cyw43_ev_scan_result_t { + uint32_t _0[5]; + uint8_t bssid[6]; + uint16_t _1[2]; + uint8_t ssid_len; + uint8_t ssid[32]; + uint32_t _2[5]; + uint16_t channel; + uint16_t _3; + uint8_t auth_mode; + int16_t rssi; +} cyw43_ev_scan_result_t; + +typedef struct _cyw43_async_event_t { + uint16_t _0; + uint16_t flags; + uint32_t event_type; + uint32_t status; + uint32_t reason; + uint8_t _1[30]; + uint8_t interface; + uint8_t _2; + union { + cyw43_ev_scan_result_t scan_result; + } u; +} cyw43_async_event_t; + +typedef struct _cyw43_wifi_scan_options_t { + uint32_t version; + uint16_t action; + uint16_t _; + uint32_t ssid_len; // 0 to select all + uint8_t ssid[32]; + uint8_t bssid[6]; + int8_t bss_type; // fill with 0xff to select all + int8_t scan_type; // 0=active, 1=passive + int32_t nprobes; + int32_t active_time; + int32_t passive_time; + int32_t home_time; + int32_t channel_num; + uint16_t channel_list[1]; +} cyw43_wifi_scan_options_t; + +typedef struct _cyw43_ll_t { + uint32_t opaque[528]; +} cyw43_ll_t; + +void cyw43_ll_init(cyw43_ll_t *self, void *cb_data); +void cyw43_ll_deinit(cyw43_ll_t *self); + +int cyw43_ll_bus_init(cyw43_ll_t *self, const uint8_t *mac); +void cyw43_ll_bus_sleep(cyw43_ll_t *self, bool can_sleep); +void cyw43_ll_process_packets(cyw43_ll_t *self); +int cyw43_ll_ioctl(cyw43_ll_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface); +int cyw43_ll_send_ethernet(cyw43_ll_t *self, int itf, size_t len, const void *buf, bool is_pbuf); + +int cyw43_ll_wifi_on(cyw43_ll_t *self, uint32_t country); +int cyw43_ll_wifi_pm(cyw43_ll_t *self, uint32_t pm, uint32_t pm_sleep_ret, uint32_t li_bcn, uint32_t li_dtim, uint32_t li_assoc); +int cyw43_ll_wifi_scan(cyw43_ll_t *self, cyw43_wifi_scan_options_t *opts); + +int cyw43_ll_wifi_join(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel); +void cyw43_ll_wifi_set_wpa_auth(cyw43_ll_t *self); +void cyw43_ll_wifi_rejoin(cyw43_ll_t *self); + +int cyw43_ll_wifi_ap_init(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, uint32_t auth, size_t key_len, const uint8_t *key, uint32_t channel); +int cyw43_ll_wifi_ap_set_up(cyw43_ll_t *self, bool up); +int cyw43_ll_wifi_ap_get_stas(cyw43_ll_t *self, int *num_stas, uint8_t *macs); + +// Callbacks to be provided by mid-level interface +int cyw43_cb_read_host_interrupt_pin(void *cb_data); +void cyw43_cb_ensure_awake(void *cb_data); +void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev); +void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf); + +#endif // MICROPY_INCLUDED_STM32_CYW43_LL_H diff --git a/drivers/cyw43/cyw43_lwip.c b/drivers/cyw43/cyw43_lwip.c new file mode 100644 index 0000000000000..8f4223029edc7 --- /dev/null +++ b/drivers/cyw43/cyw43_lwip.c @@ -0,0 +1,197 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/mphal.h" +#include "lib/netutils/netutils.h" +#include "lwip/etharp.h" +#include "lwip/dns.h" +#include "lwip/apps/mdns.h" +#include "drivers/cyw43/cyw43.h" + +STATIC void cyw43_ethernet_trace(cyw43_t *self, struct netif *netif, size_t len, const void *data, unsigned int flags) { + bool is_tx = flags & NETUTILS_TRACE_IS_TX; + if ((is_tx && (self->trace_flags & CYW43_TRACE_ETH_TX)) + || (!is_tx && (self->trace_flags & CYW43_TRACE_ETH_RX))) { + const uint8_t *buf; + if (len == (size_t)-1) { + // data is a pbuf + const struct pbuf *pbuf = data; + buf = pbuf->payload; + len = pbuf->len; // restricted to print only the first chunk of the pbuf + } else { + // data is actual data buffer + buf = data; + } + + if (self->trace_flags & CYW43_TRACE_MAC) { + printf("[% 8d] ETH%cX itf=%c%c len=%u", mp_hal_ticks_ms(), is_tx ? 'T' : 'R', netif->name[0], netif->name[1], len); + printf(" MAC type=%d subtype=%d data=", buf[0] >> 2 & 3, buf[0] >> 4); + for (size_t i = 0; i < len; ++i) { + printf(" %02x", buf[i]); + } + printf("\n"); + return; + } + + if (self->trace_flags & CYW43_TRACE_ETH_FULL) { + flags |= NETUTILS_TRACE_PAYLOAD; + } + netutils_ethernet_trace(MP_PYTHON_PRINTER, len, buf, flags); + } +} + +STATIC err_t cyw43_netif_output(struct netif *netif, struct pbuf *p) { + cyw43_t *self = netif->state; + if (self->trace_flags != 0) { + cyw43_ethernet_trace(self, netif, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE); + } + int itf = netif->name[1] - '0'; + int ret = cyw43_send_ethernet(self, itf, p->tot_len, (void*)p, true); + if (ret) { + printf("[CYW43] send_ethernet failed: %d\n", ret); + return ERR_IF; + } + return ERR_OK; +} + +STATIC err_t cyw43_netif_init(struct netif *netif) { + netif->linkoutput = cyw43_netif_output; + netif->output = etharp_output; + netif->mtu = 1500; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; + cyw43_wifi_get_mac(netif->state, netif->name[1] - '0', netif->hwaddr); + netif->hwaddr_len = sizeof(netif->hwaddr); + return ERR_OK; +} + +void cyw43_tcpip_init(cyw43_t *self, int itf) { + ip_addr_t ipconfig[4]; + #if LWIP_IPV6 + #define IP(x) ((x).u_addr.ip4) + #else + #define IP(x) (x) + #endif + if (itf == 0) { + // need to zero out to get isconnected() working + IP4_ADDR(&IP(ipconfig[0]), 0, 0, 0, 0); + IP4_ADDR(&IP(ipconfig[2]), 192, 168, 0, 1); + } else { + IP4_ADDR(&IP(ipconfig[0]), 192, 168, 4, 1); + IP4_ADDR(&IP(ipconfig[2]), 192, 168, 4, 1); + } + IP4_ADDR(&IP(ipconfig[1]), 255, 255, 255, 0); + IP4_ADDR(&IP(ipconfig[3]), 8, 8, 8, 8); + #undef IP + + struct netif *n = &self->netif[itf]; + n->name[0] = 'w'; + n->name[1] = '0' + itf; + #if LWIP_IPV6 + netif_add(n, &ipconfig[0].u_addr.ip4, &ipconfig[1].u_addr.ip4, &ipconfig[2].u_addr.ip4, self, cyw43_netif_init, ethernet_input); + #else + netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, cyw43_netif_init, netif_input); + #endif + netif_set_hostname(n, "PYBD"); + netif_set_default(n); + netif_set_up(n); + + if (itf == CYW43_ITF_STA) { + dns_setserver(0, &ipconfig[3]); + dhcp_set_struct(n, &self->dhcp_client); + dhcp_start(n); + } else { + dhcp_server_init(&self->dhcp_server, &ipconfig[0], &ipconfig[1]); + } + + #if LWIP_MDNS_RESPONDER + // TODO better to call after IP address is set + char mdns_hostname[9]; + memcpy(&mdns_hostname[0], "PYBD", 4); + mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, &mdns_hostname[4]); + mdns_hostname[8] = '\0'; + mdns_resp_add_netif(n, mdns_hostname, 60); + #endif +} + +void cyw43_tcpip_deinit(cyw43_t *self, int itf) { + struct netif *n = &self->netif[itf]; + if (itf == CYW43_ITF_STA) { + dhcp_stop(n); + } else { + dhcp_server_deinit(&self->dhcp_server); + } + #if LWIP_MDNS_RESPONDER + mdns_resp_remove_netif(n); + #endif + for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { + if (netif == n) { + netif_remove(netif); + netif->ip_addr.addr = 0; + netif->flags = 0; + } + } +} + +void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) { + cyw43_t *self = cb_data; + struct netif *netif = &self->netif[itf]; + if (self->trace_flags) { + cyw43_ethernet_trace(self, netif, len, buf, NETUTILS_TRACE_NEWLINE); + } + if (netif->flags & NETIF_FLAG_LINK_UP) { + struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != NULL) { + pbuf_take(p, buf, len); + if (netif->input(p, netif) != ERR_OK) { + pbuf_free(p); + } + } + } +} + +void cyw43_tcpip_set_link_up(cyw43_t *self, int itf) { + netif_set_link_up(&self->netif[itf]); +} + +void cyw43_tcpip_set_link_down(cyw43_t *self, int itf) { + netif_set_link_down(&self->netif[itf]); +} + +int cyw43_tcpip_link_status(cyw43_t *self, int itf) { + struct netif *netif = &self->netif[itf]; + if ((netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) + == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) { + if (netif->ip_addr.addr != 0) { + return CYW43_LINK_UP; + } else { + return CYW43_LINK_NOIP; + } + } else { + return cyw43_wifi_link_status(self, itf); + } +} diff --git a/drivers/cyw43/libcyw43.a b/drivers/cyw43/libcyw43.a new file mode 100644 index 0000000000000000000000000000000000000000..7d0ff93dcbe686e225efd2e119694d13e36ece5b GIT binary patch literal 437538 zcmeFa2~<>9+BUk+IaO3qfEJ>r1c#!^p#U+(pyJqNfd>?gsOiLLIusP>K~XAz35g~F zH3?++gJKet3??Ss4oSB-d@V6FCMIb!eO=|y4Gyu4NpMIy2gRJDAa$R8PLU9Af8T%C z`tSPxyYA{@z4botyWc(U{qB7RcEwK3D|HLg4R@M<{jv8ERowU6Y)(x}4O+Migpepg z*oXetD1I*?D!CtdI5j1=xHz|HRZ%(lSt=;}wOm%Xsvx(pTqrDERoKVOQ(EFKEGx_P zPmOyFYzp&5q+|~k0=FrlFR`)4)uYMWyW#xHgWa-1XsVS)` z_s&SlotT?CK6g@D?sz*5DlPvn!qArgMMzoEqlJXrdHVqAGd}(mOiJt3x(sR$mKK(k ztS)sIjw`t{s6h|AS5Aa%{;x*cgj98uCE1fxRU4P#iJ5bFhG8)1)DJ^!KD;i!!s#(7_tCR}9>1&hX<2750QM@7V;MPh+`{-!YWdme}+y zJNe&c{H=Wl-_=f9Xp=b-#Qo2u-*Wws8jL*2tlxkj%oiHe5BK&J8*2T^D-$-H9IfQh-G%o5XlUhzP{;ISwpxzzmqjxX$N9E0~ws4 zq=`5 zN3Vy044}kI(!5H35I=(N$HyJoem$!!Dr2AAZ~J@KZ$7~utCJ(FTN{UG(Gr!2v^>oh z#TP=+3U6HrMKARP7Bz-;FrlB#>}NSUpD4{b<|Id~-2YFSLHr zPF*DZhzCfAUV8`s1}|%+uTg z()0i`j^-8SvqL&VW~jM_(2+Z=E|=5Eqh@@G*gF<=x$PUF>B z9#G^TdWePF&7u#Cyv7=kCiXPT;l^gUpLzaemNWR=t2KTi&{kn=|M0QY)7fE9y8+$50mOZXy;V@(t_Zwp#gg*>q?Av$4+} zOW(A2qw@h@SX^$K>xs>>*-XU#tOn9*+ENKdI>d(cBzv2Gc9uxPQw)W@EMNd1Y`%+Vl{DtVxqf=aC zUB7QP#-+7=^Tg1MuPZcH*0Gx8;|O`9BK`6QWht(B*GmXbX#4t!=!_E;?3E3{@W?gQ zaaP~_HN|mepKopGp~%OKal?J{A2Y?p_)Jqw$tkY$?Ij{Z9>zCI%JI#S2l1^TtMIKQ zEASmc1bpjAA-?q_AK#%Q7k&@5H9d|ok$6d*H;iAu=E*%8zJ|Ypk7;tQ;nr+*PW93D z-gf;++B*K6{QjOD9ozI&6E}O?6+IWi*EvJl_V9YE#xh#zL$vKKb|>v!f?m@3&R$}f zfb@@U2BU<=dt=Rzru;Qlq}<>4`zwZ!2WE!0xz||M+z}kFD~VR|QTCS4+jSk`TvG?z zAKsWHFE;EAZ|N5s9?O^$Do>}csI;!R^dK9X@F0`&q^zyo^<{))dG&JRt|@csFH*GWk&KcbZ@BBKt=BP&zwi-+#p>yS0~ zJLK@G5e*J`oN>6h8`WZog`r_wrTI!s(hhmoZtKOp4?sP3HnTrF*(=k`!( z+Z6-JnyGI~;hp>>KBl*B+J1g!SCJCy!5%HYsEKT4w(NC=*V|f>mDaKGs)uH5p=ddR zmYe)@%h_9e?W|4jGYbfbiWQ0T)BZHCtL?-lo@V$(N(xs{=j*8Jh&OcPQ>9<8Ws;6m zjh5H*Tlh_UwPKYyG=!hQPY(9UeBM7KAbsCeHq3EVH-L?`@n2pdvjS34fTex$bmAp7 zjgZ^Y(Ei`j_^eA9Hj6i7Rrt7zSk=_*G_`bXM=1Kl5lm5ncTUyz!>Xm>BNeapZkNWI z%(Jm(YJG1&N(gY6+tmM3OEu?ej7wVMjG>d^L2W2=4?OY=B|cX4zWFV@fY4B+f%2~> zR;*Q}jBCAXUDf(BE^qxhPo^gmBYwtkp6wXGY2cseSa?-7d4{%{t(CIP7;h)CW-74~ znVU*vX6mv=hTpW8t{!Ut?;3^`Cl;yC$onoy(O$!x8bqL}nh38KHMh5?*WPjtW%w8` zH|#omhd$V^cXjp7h|B-7SI@Q6b*m?Ex}Do&Zze6n8A2u=2zhl5LHmr4;%DnMBAr<; z_t0>Tk8NZhi*6)l)9Sar@qeS#Ze9)MGPjYYLM$#Y5XGV$Mz7OwGbulhOWVlbR{@*6J8ZOrJJ=4@#z$t*p0m- zOR-aA*?_dF%V9ApAw^v(AKLA(h43NXgIOQ9GZPBN9ryh?>u@{EtD*OFCG+z-s~@E4 z<|tUB;MrZo;^rP1mIj z=F4`e=^yA~Flqx*ayK2l0cl*2&*|pi71t|Xu@bXEW2sW`qg_k*%GpG*HFrIpJ+IST z`nVD@r0cP4jpZ=~FAJs`*UeZSQ8X`g5%_h+#(E!8dWx~ER`kzw9oDfYA5?VM(?3)= zPpw-~7lXQ8s}zxQv0^!`i-vPp%Zn6we3#y`OsVNBH`Th#>vE#4&R4n>ZB|#_tPl4x z!G3(^rrshdZSdqx){?DQRNlN#;VE55bRj1`+Bu54J2hLwuIQNRmcL%t-*Z$Z=4$Ng zHJolm=CXpIkJ8< z*8PB_yY=VmVlL+Y!cTm6W;^-N>oJcklr=HgGoARp;TuwI<{K&^D@kmfCklRIeJSEr z1*9w8?iEpuBb8R=8bT}LF+w;JBOQC{K18Xd91)l`Y3)=s!o3^}LcwqJi z(Hor+t=#niDcp6rY*;kaS0Y8a8tTcD&Ks@w%+_>FB~gOgy-;{>Zy7vNKx&jHg*(I- zDg)LHvctYXo&j=#((PnaB(LenAk3J6^qM>{=-rjREeuF8-NP+`Sk)hIMl3q_tfGmd zDQuQA>{c-nI0JYlumgA|aHgFTp8(FZr)EbB`R>I+sVlms;nCzOx>oHg9d1SMBlYjQ zlF@!EMWPHFGC-ef+|2ygEoPFoW&9k_?w`2LF)c~I3K<5XuPfEsKtP`A=cUH{jsJ? z@TgRZ0Pg70Y^691_)3>n!J)w4c2R9Se@|>citi?7PcvgVgE4&&X@3IpfzE;$OBioF z@WCZw!MZTAN=`OoPo6xd;0-y;@xi4C%LkYGTjp3;q!`m}=8etRrqg|9=9_!^V<)nO z*ITeM&(iQ?Upsp#{z+Qj6+=UP^je>Y)s^&0KkI6UR^LKK5$ol>PbnVr>#l^MbU)~v zWolup)W7WMqW2PreyP6vr>ul^1xE=4x2K&3R9@lm~0oL3j zJ&qm2yw0ae*;uBI-HjU8W#F3Q$D4Hg4^;Ac2VQ$H5SEGx3S#4X zr1^o#{Cr;X(@^wJPvD__yoJQFJ1CySvpagE8A>>(Xo%G=@RsN0v36QwW38DVIP1$x z;VEBU>X)*w`dy4x#yX%bu^}Da>Row`o!uRf9`7P%3mpSb&*ay%WAxlJ(i)9biPn6} zO|hMh18n+905q5*Bo0Jp>f7kMIfsZKvf%@C z&+stE;c_x+>Vaf4<3B2V26GJeLCB71Zy(NzCew{1LP- zZR>Gp-^n0sGYAiU4@iH2&ICHnm&0D)oC}>Lo9>!7^3eiDFTAYNJx^rxiv_gwqjCJY zU@K3xN1&CbRnk_To)a>rQvOX&rR>O2z0l4ZcC_{I9+qc#ieh?nUF@|u{&kBcMX7~= z{hwkJjuuX1K9dR2b&;!CO6vxF$J3|nTvb+!m3ga{78OjhS0oqM32qn{D1v=r z@&xh_?u05*Qfgr;DJXnM5mHkMlSzI_UTH!3Bc4J;RBRPRY2ibVlalR0gH@|nPD@TE zEA!lW1qG$k?Dol%?2}X7lilMdCnZl#Nh4*YB`ay9q$D-PrNw#6%4m}IRC{W&y{|Tf zs?+Sshg6j36)!C|^Z}?ldH@!t-!x z$QPrDJr)A*B$e4u|3$?N%>^u>WacudHJ+!?WFACf})3V3s)gO z6)y7>l|aD9UA(fmBo8-~f`Hy-FJE0ogPG$26n({j{EQ<@wt4hkvON&+&n3Wm=macp_ue9)ItA!b}=9%3q3&tm#3rkB& zN`p@kR+N>{X9BiS1#y$jOY@3~3kwWC$8ndG7AgrBtuo^tJRX(w=BXqx*(?;4npYN; zt;{QT3+7Sw)C%(h3i~CAg?D2_*+#9NGHP|=sMW}$yl7=%$?Ec7EDB0;mB%ZS&C5`Q z)vF3CJcaJ^!UD7U6vjNNPl0-EZKH};k2R}b|1#14c~VMy6k^5|mgbcg2HT{!dP-nf zVKEAFTga*s+7h0URb_?drI?Lor4xQ`7d*@vQ*K5}ne&TF+$+q=6Oi6igH<;_oL5v{ zv}&1oX-TO$ACH8PI@9gk`LyO=ZPlPXeO zFr>61cWIux90RKmey}`uW!bVa%;vnZ^4#L0vU1{CnXEoD%PmE5^WCeU&IRj*1!x_j zjB&-ja1|+39*tr6yO%DTT(;UnAAr%>&__(pEzI*gREXmKN}XH2vVybEf+PIW)b}}Ocvoo(S zFTaQ|ae&&1GZW{MkOBc z?Pn!}s})>t^pR=!i9Rxg{ys7ducYgg@=@bg_mOFMXCIkHmHWsv{2i>j>PL-#u#Zf` z_4G^msNn7l6t~ZNHu_TqnTC7&|2n+0k4(eo7=Impe;=8KKi5a5<*V%@ z({O*}uj6<2k!g5V)UU$}`p7iAypK%NujnJwaLvG9;`buTIigj@-!D4tFHi~pxuX<4 z?xNfl{_{WyhSS`B`Ecatj#HEzuH5@-XfxdLi#eh4@Z03%+hoUW^32=hxwpx8-zG1= zO@8(^dB<(?pKg=?e4FgMO>Tv(#rUI5J^=0Y9rzH)bjnfrC-4}^i-U4RpC+aC9|3ta z!WRX@(;$BdIXWn3LT-mVASf?}d;_uxO;6J=hTQw1=~dq*zXdrGjV^M(r_P>GMh|_d`VkkcS3kE94jyc6QKy668XR z&))W#5BU+uwLyC_vYd=8AS*q&LSAuhd69cXSuXZQD+^b;S9(ZUK~YI=d1>CNvZaNk zcom>ve9EtN#IqVNaFmsouA=6i(xO%6OM_b;cRsdbWvfdIbMqd~TT%FnmM)sPLJ3wZ zSYwB?+EbqE`T120MC*M&B(Lm|RqkA6ol^?rd4#f+B@gvUtk?GEw@gr$VytREzmxLo zw?+Q@H&i_NtC!}wOFWO@)s)imqP#xuqV(qTzw*wC(wcP3T3nbb6fF~S%RGgJ1-YsD zc!%b{dmrTIy7a#5f>xlLkzecoKmW=LF=Nabk_Z_c_Yc`2=;nWfKV50GaYrR1dpvf_8MhrTSHHk5vDA$|n-C2b}8Pr*ax0H-ma3<}TGA z12;^`R0EDav8Di}IoLTTNyy*BRQ=^3 zzZeb~`8lw@Q+pTX=r_9l(|pzjd1a7q2=Z4bk3;_i(L;u401o^v(Z2Bvy{{Q1&wzi$XkQ_OpyD7{37MZ=lh_H$L&fy zy8oc@bAtTtAYT;ZbpJua2Sg%2w9oP&e~5DAUmcX`K7`tR6XX|z{QDpmgS;00oW`rC z9O?ZOl<7NtRHpkCTFyC?({cs*-9dhTkh_AM?q8_gPvA5@-LKI2_hbGIPr>9ISN6!t z^1OWT@=}!xy{NRXcw9N|T##`EdAM8|M>q20aC=4(R8C_hjY}fq+$Ael;u?jFo3UW- zxV-Z6(xUv;xF>)N{-1qDzzjtqn0CqsLzU=J*4_`Mt@4S%cPPlANEpu+LUv%TQyq;@ z?J!kvgG-eWqG4&0COq3Qi{EuiL01K@fTJGeUK^U+}3 zcj!$#7)H~<6jSVIy7V&!n~=WyGipOA2ZZPzFy%87cC>AJKh%bPDDN#BmDj?~jxDDF zI0;1C#R#J9)TcP)9W?xkJ`sDxz3&dDCQlfj zs=ST(^Sgt2zohx=cL$5B)X|{U*Y@*{x-k~_`py4mh-8sWn*aZdV&|@(3sf4;oi)X2=IfCl8#4U0B7CbD&G0@v!-HBSTscb{g`hTNrW@ z{7LBDAl)dAybeALb*6FWk3qR!V98(CvgBDzzL!Dw;ek`ci!AwVJxi9XV@cR!EO~Vk zOFn)MZL*#vKIpc9sz7T%e?{2YDwZUGpWn!m8?Zk)j3YxvaAYph$OO^69)pd9d>Dkk z{47geM_$(bu zh&=uZ-P0(~y}-{S&M@FNz>84kI@sO;qUE3z2fXhomTW{=CdxSlo$)3Z8S$h@en2g_#~(c;eSKeeO8YA7GX5rh50I{_*@@M`aO4vDf96__ECa0oJq%LP!sadA!;x(8C(D0H z^Tmz7;NCp{-{K#S#CV4z?3>;stg|ygXS08;@3ooHr0Vxs326guK^i{LdHBM!sB z`UgVZ21V{bU3cO6KlsUa)O!6!M4k4cjQd~@S`8}vGwjfom)=7#`z+Zrv(G2-3ZtOid zks(D>7;-+HAv?1fQg}B*KE_4)`F9zz9G3hBb0Qn0y^kaJf@(ltf;vDq zK(|2eF6KxhXbi?TLzIu+Oc~Z)4OoCv*LfO7iRyZBFTV&IsyFELWYrJ=d>AM+_@nP* z{QL9o7Wj7y{JRDI-2(q^fq%Eazgyt{uPwlJUd3(_pUzeLDZ@L?uTtJ4EvTpbrnC(^ zTguM_x#cxgeqXV>DMd94?%Kg?C7= zDCvmOnxLNU*6}`_RIbQBO5MS9M=0t3C>>PN`B4f4?e+xuRi(V0lBmS%lr|{&{va(^ z;{PaZQ1q9B^}Ht86#EY8mJ)tNs#MYyrOS%`qGVI@yC{7Z%=cl%?t=7*(oX-B_A2@d zl2hSdOJ1cM=cUbx-Fc~Ak-wGxQ_1&RX_sR6jr5)p{~KwflFtRHpJI1G8XT0rQ25u< zhf4XsmaZ!0`daFz=+8?ZDCwP-nuGal49cOw{1*gyof7}NbW6$iy!2`?-S>m(zNy&x zrKw7J&P!7jy)qTP|=@}1}XWSk>)DpIxBsmgkP3Y6#2CDQ;?qt z#(P=G|BN(7;isgHO86;hnH{J8XxqCYN~f_7?uv zap`d-yfxTg$AkTTEI7W7NpqC?9+Mtb_yy@Mr956KOUeIl(ql@y{Y}y<{A=k&h5My^ zCEag>ec!3sg$AQ^Qn}k@Xw@jCH`m9UlsdLrQa&?Kb52)|56FRAlVdtRJx+n z@2}ENO8k!{O)po%KbBrs!oQSqmG=EodR)`hD;LQ)J_%N`iRK-Vuv&vNL1s2Oy+zLGK5f%G^JJ+iC zBJk$NRV)I36vQ&cPpEnlNyxS;73+b$PpQ}lOrBG*iRxceu^IULdKKG%tGB7x4!q$_ z6{i6kJ5}re&XQD|1-wXBaSm_=yH077MZoX(SFsCt{|FTez{}|<1H0Z$@X(zqwgLP9sA4t9N_L26)ysQ|05N< zsQy1yEC6S;sn`R2@SiHK0CvP}Q2MSC_(YkrrIw% zfOFDS`#r$VWvlog@YJ~~J`8*?h>ueITUGA`F3wYNEASk*iv7Udg(|)Xym^(1Mc@-2 z70bY1l&P3Lk2gN5VmZ*&4a-98LItZU~`U&k5ZevRO|)5 zf2V5S3jF5IT(q>5$WZ_3nk=u2+3kE@uzC$Qm9YFs05`DRsb z0@lBzVl(izAhrQ7+O6vCz;89HI1RYsFDiBbYd%zQ7PSxJ9N^X?s(ul0^+zgp0e63* zVgcCmsfsXD8-JtXR$%+b!S<&%L3|PToujH=1pXpVwU>e4 z%2zQNgm(A;RN3}l+Jdmhu;sx#w zj+s_!U;ebxr+#38Utct%DC_`Nv>5-t*Ka@lAHk6QM}&34454Q~Cwy4+<2A0T-~M&r z+NzNKToxmcxE`;-S7#2~Lz=5&@vkla;mIroX=dpi#Kw8KSq6bkH@I-Z5(xw_pU)G& z8m3Xg4yUsY8cM?|5ys966>2Tji>Q4q(xdV#mg<~d`Rse|9zrVr<%gXeDHvV)q12w1 z=bo&4XAz4bhY{|XZE)N(ufO9rIDsaICr;Muz;~Rlr@cFN#v+5z-x}rUpU~lD5*V*0 z>8EymQg(KfBYVzv*c0&sxsoU1XL1#PsXY_A?|fk+Vg!DU)nOWW!SM>h_Q>n--6XH) zTia*MinTa%CeC)us#z4U4sj0g&KIU<4{;9iMhdCfLmbDK8~xjz{k(_yaQ`IO3~}nc zX_Py*IB)tUWJeYaadvxW@xO6ueD&7P7a5TU<4?-|e9_R6RtG@|iMUC2@Z)CbU0Hl0 zzH^js7e5ww?5zH-v2zn=MYs~P5>b22;VNf$t7h7}JbCr|bffj`jCY(y-^lQ{$e6if zT`TyQn9*6I=h|FktkyeB(7H4!8oOrdjWbnyEZH%$B7`5JBV5J&H_>nN0*@DXm?wEw zJaV(A9i3nr7!vGP3{?`qOKb6ZyzB>p+Rwm;A)LOIWC9PT7<)MSKL@mLH-qXyuYjHd zA%vv0a-4Ug&SpB(V-{{0$#7+vt#ZsKr2_ufEb^bpGTG zh9az|-F|>rL;N4#|Hb`pJ423h9Sj%JTIc-9N6hwSdR~sbnE~SB>1i+P`MGUb4kOMK z$o6GBIg#UzMRWe}`@>}7VC?nI8@>_oVOI#pWEk2k;s~NQHC`0&*bb`3|8le92)0(w zq=neVw4S?2L``VFDAO^dN}<>Hz8>dWwud zMvkILphyk{sZK zs78kn%hzWbo2kt~*l0um-Qp(Z~}tHzc}ZO z4m}&~T4D;%B9U&}*Uv{p4sD&fW;Hn77<96Q3@Sgd4u!!g8nS zS*O-FL|7s$FzJ(LLgRLE0`g$jncj5j6q^Q)D3XSj$tt+_W(;{g)uuxNNj zy#JIj+v+lAyFuGQ7eLlL$e`_@3m|JgWYBid1(4MZ8MGaA!Hu46!HggSHgQopJ5g!>bO zVYAz6jDkk|=mwLD|J!XeWt#+6oYJ;^$RX#Crw3=p2_}KDuwwYl!Ty1FB~@%`GSr9t zoa^7(3`(xww&}AXX3=td-$sxhV@>gB#er>+I29)q{r7e2)8rp@9Qg?SSPps7w;aj9 z9591wzj&H3$QA2C3vCnp2Y==h2O?%iWDgP|X2%Ev@jXCzv~h67s>Um(3(?&5$IEr8 zZyCtufi=wL1vTuZklBnVwmpG1relTnA00n5pTUEx@&C^2m!~um>-zjk*=#r3wc>ki z4F2!gbHI9+UBJO--Z1fvuNbpdeE&3K#_2FU%*et1VcA24Q2zyCm{aQ=b(zz;g|NnL zLVe~)A)*mmZl6|+Y#WrV;Z1^8tUhfQ!o?q22V}!XJI?#a*mFMP+yuee7=yXJ2o}CG zz0wl&LA#fp`VzQBloQCbVr7E|WluwSJs<}t3q;>1XL0TWlN?Rg=$4^qtKN2^n0m!m z_ZaZM`n!4p(gQdpE+FLv3=Lsh`)@fG-LE0y)gxD!(8w*uhE;cc9v!~roJ`hza77zd zmys;A%EZWCCkqxt&(1hzTAVR($VgM@=5z8lZxqZam}e1A$t1^}^{#2Mps)M*3LE~V zJoGRl_O$97La#smAXA4vDAT1h7<5Tt*B>vfG3b)nI=yw1fo$aJ?&Guh-(vi=x26bY zVUlo`#;xV*$o0oPG+y}i#~)%4OJ~=mR2q;*vTnkE7&aN$T1{P6mYc^RB;u#7p?nf);^Z1yTQK!Z>IJ&Yp4i!fW7nyvUKeKxH60{M?kIoUg z_GrYvpoCg+{b{ZE@M$xA$3x2Z+_tWE{ecI0>>)*MD?KF-`$dtwH}oZrNC$K{xp5$D zN4G87M@E_Xh>j3uIsdL4l0#n9in(V=Jw1`{jcyI!+8D=^twd}-=N7IGU3P6CXTeJ8 zb}^G=`0yU0tr4o{+C)x2GsE#y8uzMmbZg>18&A)?x))`V8=brEdIM*Zq~TmJaYhKvGP?umJ=3b;X$=PSjPuj8L*h@9J8h?@ znhDN+2tf%=`>xfr>|GKvr{%zk@%-)zoO6+~+cVWd#3ASQ3U0xf(Obr4N*OQIyy;5E zi7|hux}daWM(f*db0zVUk!HI4sG@z%Se?Rp&yng6uMK3`D+>p#hfi4&u|#{!q|g3h zsMT>idcEsNO;r`w8NTpH6^S+4ZI z`M`*~7)t~X{~fClH{B$$dW#N{Mttrjo5=7+pYAfz4D75d2=Us5*v`s4?6t+mZ;s_} zYKEW85H*?@zcvw8ouuGI2ct=AAtMiIBTw3e89`g&W`=0i=>6lH>_Qx`MSI8&jrhCw zXuHbI)K|wfaoLgZ|2Wx8oKMfFRmv5DJzxaRi6gObt`zJEnUv@Xb9|TAurFQ+Z*<5O zJChvm3in&$Lw!{u!=yIm4qsfs$xH%?zv-L8Q~T&f68BG^IsSXPl6Xn{SuakSghg9> zMw1OYMaEu9=-Ds&CYuZU#8h_dUwv5HEe_dgmYXLYh=RvDE^o`>D!Lk(odIcofN9Y1 zQ<|!q?(ieNK*T4$GBy4nkVMI6@UIYd2+S4>_MckuPp4>a%{F+3<)N%&m57sgDUdk}D`aav_FM^^ zFB5BgnE3rEtFRrX5%!PQv}&lA%fzXH?{f+LeU8}|iY+*etIiqf%P$T|smpU0(-V54 zU5ee)ld>n@RahJ&bQC2EX;~j%;S4yY_3ZXy)Tho}jJ-$Qb|EE;t-BzQF=Uv`vVC%LoZ{oSSexDNY#k1R2XgctMXx)VsqhVn!KFG65 zNcGt(f;EfOy?7D-HY8S^y;7uAQW}v(<2`cL_fr>5q__SHTIhTHbo`8Z zx>DH}j)YIig1>zLR0sM5bR87+GNf#%5T{n%j+{+n^u&# zz#-?jmhZ@9Y+QPFVT~0u(qGE`QaOO#KSV@?7*swsoAy+U!1yWO^$hiFBvJOUexA!d@+){GAne%&6*qAgjpHy%3s%V;&WZNH(?{< z-zq1+J6;Y+^ve3mbyZ0?nTUwyGjTYr$bnvcOm3FHw(C1sayp&r5ErKgmCAaYIm*<% zD}U$O$1nFUn!URwQrO9}{@R+2e2l3{9%!B~Tg)W>Cm)TmTZn#S$S`&zx9Jd89?qLs zy;~lbWAbxbX3y4lXow+w^3EBuF;Q0XN%U=8ULHci;6#|gVuB|gDfM`5vxOHat#Vv&Mz;qWD< zeO*_tElh8gzcV-Ny)XJ*`5SwK33aeD4LfC{@ztRwe$q}BDX{YAJoBR3#wMlBpZCS_ z3zV_3^vvJUQu}IlbcB=elzLp%Ms$3~?5koedt5!zw*jPXr<&90tYt@sfzb4Oq_)5; z(cw<-bd)JIou)^a9&ZSJ89-f=(r8_i;&?qy(M-m;NjFf&=-`a{b3%*ds$)GkJi&O0A*nQ(P zv6=Z3E%QX8r{fho6n?PB;opYUh7q@S1xJrl+m?oVeRLFuotftUqd=_t9^8!i8po%U z(lXN$m!Wm_$*$!L&M4O>mp&4oy-uuTkA*g1{vK>PAGwrA5aV*Y6sC%`hIe2UoE zv(y95!Y+itZ2a+*PMKM+VD`N=Uza%Ct4~b!GKrj*T1^PN;8*=h$Z;wkzD2(i0#Euk z%a6yBc!yYpc$=9M@+*-V(S2$))hAh-re?dA$E>W+^rPqNlU{e4j-8PAB$0$A-n}&^ z3omRr}1sc7UXYB?rKuf4u-Fl;h{!RTLX6f zU2W7FwhJPZ`p(8E>8oYai;)UH8W3HLDxwd0hn+%Woa2rkQ&6?k1 z7xhzggK2x!?_Cazp0hVJe;OmR5jX|ULeDPy_!iFbwol@z_t-P^UEm(+(5)9`eeAr; z1}oR;aYvoDuplcLrA zYZ}(v$Fb&SH+s?TJ<_`Y65HE1iES62Ckc1?Hp}tJF^z5^a*8%V-*!SC%Gw&aikL=5 z9C(9{1RB0gz{(Pt5VT@iJCj(9or_8LnK&_5#=PAJD+^tHERFd}uhh46rtHQ#8j!ed zs^2A;`D3PCu3a^8{PF1BRrG9heIN(p!I(_voiQ2y13nP*J}IsFgdDDD!;{mR;s4-` z=njCUcBbou+?lijr3y=;>&8}RxEH&E*oNp6GO?WATj$g$R{%!r<||vMPxKrJ=Skdn zZ`N{ROIG#=Bw-vl-7my@eR4Nu)oAa)yZ(+H$c{{SCHRlw$I6slN$-w><~hOi(_ZX5 z@|Gxh;};bEWxgKdo6*v{H&M%OhQEJ2DIk4_t2FAZG5?#rGD)hH*TjaU9|pSIxLBt> ziTzP5&eV2O4GoVH4gH69c%YGTuiP8ARfq}WQt)x$4_irRWlX4!%NAw=-IYRanh zlN=2xE z`!qaKfzlTRNtJ#sUf1fCvmhVFw^uf?6@J#j;1tKD-8%(bmlHOLwe(22IL#8*mR(01 zH_O`OT|#yvuCt99*`KD@?B$Ze9H-N9^=_xv-p%+OfYa$)_EzJLNmOM@<-4-Ro?H#B zebe5pPS$%u9%+ehJcX4z#7Iw}ALvc4rXd=H%u&iYC-yWA#k#)Lc_*|vN@;VF;{3ZX zQb*=T4cqP7T{C1v&EB0=4>aoHw5=zU8hnKBJN)6v;Zt_Gc317J(Zw0tb_@DR(G{%~ zHGB0byIni01~+Y^yB+_wj)C0iy<439;CW4~8FM145o>}d2k6>~(>+B^fS3ovuZ1Sz zymyr1?xYPEiF6F#jjr{i?Oi^g0(OeUH-c63yd)QR%s;*(W8UiD$6tZ6VkJ z&^o-?L;MjqjUAVnzMf`f-%*5fz~MJ6`NXPSj(vare>T<1k0tGc57`j81>fpUWVXW~ z7Jao@egd_AEN_EcnMc=%T6md9Z*7pD$XiZAPGScyUcucSy*T((?0J%S=P7s51HxcY z6Jo;bsfdijI-?iAJ43$*ouRY5B8iqa>5RJwCyWYgtW(tBo<4s4q9@W%uLIQZ62wSC zoKKaQ@@aQbv|v#zkt*i1L%dRXMW;jlOsrn~4_Gm{?=iDyoKAm|dJF13=t!d@cIB-d zy3ms}?KMg8AxSZfxCa31aXpu`be;&x*bXH9yD^&`2{ zPUGptC(i67uJB8I83vUtMc^ zq`!B=Z{%g%HO?^_Wx{?@{Gly`$Bh7_z9I4k&TvJ`C%KD;Enl*Hm}8JAYU!RsFLs}e zgm2M120M-d)XCH|eg1h#R1pg)vQcG)C-b z%-GRP^`VT|vrO~#uHu|%_=>LKsdRP6byskwbIiJ;Avhwrgwe{5&Xydl*sOqeuvr$s z@7KrHIzx_GR%{X$RM7Fx#Yg%Gb_BKsz4gC`)_*>2ol!~~)!xL8Y_y$+cg1zw=QYLy zG1`77=$_#F*fYv6Lo}GS*6=@7r*Cx*Y=Mum;95$#!xWH?9a=cl;AP{n^W=!v(6kO` zqDS3iuO8b=`~eHSGG*ezTcXpgmsz$Fei-+--(O!;Uqr;RLp4PlUtKhWuIqU6O!p{H z?%_7|-^y+@Zn*>ZV9v^E+n7xaJW0S#cg!1&&kM7KQNOzWa~2Owu5&WSDuwC(XKRep zj498%o~_F9bH&aT9Ip2(OtsF@EpK)h^+&Gg^#}QF!i)@7+}n-2Jhu5>ckz?L4<PJRzR)W3AaHsR0Cw3g|ZC#?8< zx0X+9LaNy7DEotXtoZi(^KqhVCH6P#Zjgrf>b)5)F7is!(XuZ0Q0tU}aO;`^jrFf`c;$50W3KmIhYIL#AJO}X zw4GlN8j;5#VdI|AI$}M9I~@POlgCQz3?u6L)%CB_7W2i9tN*NeREP|Z*ktf-+WYLx zh)vpK5p~0PeO-wdp}TP2z(+LT*=8=+Mn*@xq<^XP{O%58*y5RKEp>dpum<-h>2-R8 z>FesGVIN+bJ%C9*W;zzr6^*oy4lo=MFt+K;N9s54LVla&6 zqx@@D92B;q?hE-Lyta-NE4#D}q>)tT&)T!jAS{s0uIY_OU`yj)JfnM+jGpA*{>%c| zYW)4WgNnDS>C)A+;=-~3Hs!%u3u?t^pm$%g*MP%%Od{JhI8^;wIOxBjHc^vK4EL|@lDs)KQY@I(n^10 z=d> z_w8r!p2YN1J%JYsE6J_sYC`9g|4Iz8@lGWLuCuzyksYx$Mj*8`?(0Qye8ld9nH)wD zp5}>9w(9uL_$1U0*AO#88bZUO;P1k{{dY5U{dTi;4CWH9({YA4p3U#!>U4hN?uBxA z1h?t=i=l*C&~z5?2^c?q$4*LyP}8& zB7W7T_hY=8$+&?nDZG{6T7?t0>-sn1Sz(=iOHxxTPp$P^Sx&5qX<$>ip_VzC#zH2YRmKYXc8b>fKZ-_oIwtU!iK9A? zNo4Rg3-Nm^s>>USiTN0wUq6Et1}i1%x#tFh)9Ojwkrkn5*As-0fd=Gc-E{XQrEl)7T-`XWAPt6umaYUG!ZZlj6=}{TFcO=t4d{IbU5T zqzOWj8b!599q*!tdvZcizCdA7)TwRxG%oZ{(^8 z-le&)PQzRLyHT#)`F~UHU1_~^X0Se{VarUTmsl^XODWp1;)ng< z7v__V^j#ba+H+aA-$iWUxJMVT6Z0Vd7H6dI$cj3=8}<}>GSqJ^=B`v~7vh})#vaua z@0y>_`S&=lou>9{n?0Gv15?C1x~GVvx+jZF&lJ&zr+bsd_i*oKhPdX&E$I$C)1p_M zJyKc|{gn$HkCkKOblmMIUyn8|8jN?G#(Oynen%t@a$K#h%f}{gUM?ZZJ0xoW^(bkk zEV}07*GJN*M9JDm#u2Akfos-|Sl$ReqN7y~AJQrtk=npXt@6-NQX2++R7Y4Ao{wJZ z-@&A6#{Wb1q`cyM|G4^Wa|NC=tN}d@`s2`QQV;G0(YZZ>Cs!Cf>FCGR&s2V)jpy2G zZ}hX1gqf%ANc>G(>{|C)O~(NI{vu;NZmOR-;rN9$Z?1tKwq#vpxUJ4)-_R^gM-;)07ae-@u?vq;FU=&3@?|EDXxl6&+BeH%&5G}KZHYoI8h4|6ZB!Fhz3Ids&xa>#u6)QY#66dduwuq< zU;C=_`_t~V>(OiOaykPEaS9>X#sjnSH2e$~vCy}12FlhNCdFE1Y^Lwc;8|>qmM?D1 zz^d;qisjQ?T0HAvMFw{d-FXQ$%#;M&-$_$!>Als=mH3Se_=c>e3u~j`A8>yPBai+b zrk3|KF0EMFl-sy$rI~+YCGIj?4`!P2+@6LX3XI2ZM#%I&52XG0ZNK!U?Q2sSt!u5g zI#lnMY`~oydT%=fJHHod*v1y)e%Vk-Mh*1a`SUgT@CtuFTgBHSS9pSJMu{1p)@TPN z7Di0MFDM4a<2f&$z8`XacN+J3{n&MAx39G#k0|63knYC4Tza3_Su-`x)-pAg<2O3T zw&?NOQ1w-wOlCFpkJ@Yk-=y(BQ&VYrhCZ<|k~rDt$)s~#4deXJJj2-4kQ)e5*K+#- zj(@K)B1mJc1Cba&PhYI$}Mt&faX~?ZIcz z;sH&?xOp5u{dbIguxJjEdKyGX_cXZW!Pn&S51jg<;! z{CoEg5HtGAzAzW{GGeotAI6WZU{daoHHU{HB-}ex)Zj|MK2_@eM2jAT`81uHln70j&xmK5ynH?ljOjAJBHZn6Rkeq1C9X8;#xgjsYS+;2x%H!tE|5+ z=OwKQ`!lj>u3ztPLR$}`l}2p$bZ&Yk>QT_Nt8>k1>Lmj`hp+Rwy3?v9E+;s2MtAxz zpf~Pno-u7zuyj|s@Z*LG?2{2euS~fEJ8 zX-YCPMb|~o;+BjCQa8|3qCAb8rVd8u79f=UI(^N~6c%0x76>l`Ls28v3D?tzD=U3< zTp6A!{Zf(Oc&Xisf&tuxBaweuc!E)V@O+7*P69=d4qxk}WwYNaPYW<0yOF)F>b ziCdaOCSGP5JKGV@QtV#II~=xzfY)XW7;UiuNWLGB#*xX>(e(@3z`<+GmLWO{K4%gA z7hetJ@D5WdcEiD)d_wzHK>nHg300SDYJS2n(w87P@>Icb>=&aeM;~$P#Mk4-u@=eU zTyR;v;EmB=jQ($TKyEN!c6UN^>G#VwxOaNaYGYed*e^_nJpb_gepRuf$g|9`%7Ha{ zr_r~d*E@a#G$eKw?SQO2$rCTJajIU&^aY@{s-^|KOg_z?<=P7Qgb};)LMrdNyu(!? ze`q8g)pdFP$_n|E5&JQ1!5o%fA!i%)K0LKn$QS6Um)R1K>y3EAC%TQN8{~R>w6{Ut z<VMiyCCXXhfd~`kX~c1p)bEvv*^XV|+6H`u7?S%4Z$NY}>F*wlEGqo1HtB zb5u6I>%0bz(Rdm(j`W6Hh{rMBZ&1cNwIryd4O+g@qIcATP0x6$A2gFVb*h zcDG}8uL#JWdSBX@1nDceB%x3pYE1y=R8w=Zy!P{|Fk~${brt zRETobAa77g+wR+`l=gFTK(1hhmp6d&ZbW%kJ^i1{i&)GJaN-e_m<`Yf5FF$O-W z-dF0eUS`=S*Ey}B)l~$|Kj`hGx?M%7o}^yp>7=I7Zqgjt>4ud8<_05n7(|X~7vJ>N z0XBnbnhPF7`7Giw)cm7G?>eJ`lMBwF#@^XD-SK}Z({Hy5pJ5CZ;LWGYG8_jsE>1z1 zW#x?-4!!jp=nx!3Z(y_8IZ;Xr1I0=IbAX;vo(>{+?j(kQ=a4c58d}57rBHlQzvbahK_^$1EVPY^DZ`8O? z#kv^lW9Jw=@yfqMOkVkwF({GkM0~ae0HCov~)@2nW(I{v2^^Ty}p-rlT&Io%^xe zW^ei?Z9^toZrbaKUCPeb>rUIS$8^q3Ur~7a?q9#*fJ-vsJy=)D3O_`3ie6@q_Ju>Q zH_`fP_6ap)nZIIIL5{H07w+l1s=`jEt$0Gn^dI`wB0HWJ4;2!}($>cUl?{h3gjwJO zy}{{9xQNDEICSzQvG|Ze3CI^eeT_O&`LCtFUmt8x;( zjF?!4XW*Lln^ysAoZZ9;s2L{LccT1=lWS|-!2l~=k@CL0%*=?5I}on;e^bIHZ1diA z(6d%Es z=tZBWQN$-oX@>R4#t-v^3vMgG-PjoGQXOG^a?q;Kw%ae+a zqwgP=b1N_+F0)a;Us&s@EpGuDO)qHofsMIBDr|AZGa(8|K(MeisM>N?Y{3qe4jPJ%j zrr(+L2)*B~+xNMRZwLBsR#&p%&(y&Cn5gTJSNw`8!PqGB@#QL;woTP-W}aU>(DT^U z637aE#e_p&+|W^8jOtoYuLbpmS-6CLW>I+HqZ#1oN7lRUZ=dIq2&ld#4ucF7Z$xtC&JHqTv% zv-}3pkYA(yW`cI?F9t1v{tDw_rWl&;22XkY*_f)|z+~rz6snDFquIOOKu?LObxPh9 zF_ke#jyhYK*edpQrZPuZfo#mH#wibs}vuVQh;Q z{OKDC6Z0lJ_id*Nt>j%9Qx#Klq&)WMe2JOwl2v2S>ky}NFwU3zPsl6K<2Tq_Wk*G; zyueF2WoO>WC#8m*Ld$-9{RfRNqx*5J&*e5)^;J4p&A>}BH zO2$k|OB*WUqsGWgX~3$c0krXeJqn{S+5swaNGCdJ-?|<806-G7A=4 z6f`#1Xtb@4>yuc+|>;r%Ff$%s^q;85y5+k99*WHb-J8e#(=TqpY za3gCy>L8u}#TZ%48`z~CyE?L#gg#A=4fVlPM&5)&pAAg7%&6I!pelh=C&u{VAz_TlyT(04)}K9C_zohkqlGcMr%TUQmwb>?BM34RH5NCkAkn@?9mBYxI}R9gAvk)4Gub2oIMYlRVQvzEU7$gHLB z;GYQeedf}-NBF9lblorm*Id;My7o?Adf*YQ$V@mSaIYT~_}32$)1b{lEfS-&NF)!D z7FpOy_Mg-yyhv9{4wQDJy6x?vuj264Dve=SJ7#ujFGumm9Fg3s#mF7Lt%B4IW6^Q- z5q#a+#n+Yka{HpM>Mlp=aE68z_g04Rt|Pin)f16)Lj$cTBAsTM7Ghp`0RM;acjI4x zf6LE#M#TBA_!GuR)JP{y?_kn2$g@uR(FNjT!y!N9*mQ60S_}l;DawYDvW{T;e#+QSlx~k;-y0_ z(nz8ivs%CmR>8iG-F?Gs#hsXkQ*sNJ7P$qwAhx$GB-GR5;U#yBoZy@k)VzgPp+t!U4LwLU3KLwlc4? zZ;}nFN+|Qca%l(Sutwf>K_h_j#@EgE*DZK#f$RF4*0-HvJM>sEpG8`l+OcMku8c>T!d@6>#R%H50lGz-6z89VjL@6u6G2_LC_qPXcwXmE_+xWufv&{FdC zlP>V)0NvN{s+Ne9EF9VszEh9GbMVXCF-Fo4xBn*^{_b}|UIwBTcFlFm{szxZVq}IxroJ;J?8LWW@8?tYF@NmewEh~zJo$Fc zBBSCNlw-ay*X_Ej(MGuHxsW}FLs5PC1zOh-og7|g(cg(-W!ro~>&{gA#mBdZgJq?} z3+Uw!M|yb7u(}^!qu;bqKZvxg0sVFwa+2e82HAVR4&E!?<*D^Y+DzZ|^)Sx$^V?rV z@}Jbkc`U>7PIeaI(9s)|`&mwdBEK0b#qhpz=v(nfIi(9giyF%bY~oSIjj?C;OJ?%guiagpQ}yczmTOcj4fbvQ@3)#Jae zKE&6kYE9N3x^DGczpnOAajR<)4qOL#kChbeLsM1%wVqo&2d{HVScCOe&zINDf~H1W ztCNz>bJcoS@{=S`C!J8*@U)^YeXuFA+6afbK}psBmdlMFR$HI1*Gj7|!iR~K5gNxHjnEnI zd6LRtAeyo*# zdU1IF(@Oum&{M*u#rN?&95gJF2m20<#!Mx@#fxZVRk{&YsAy$cQ{@BA`P|4{*}(?o z7A9?D89Y_EH&!p&0iL=BJ$oO@pp{NvVA3LES#zE{>=pPUl&{zu+&j!f{*91tE<$At zu7~oF+u0a(95^|eA%}WwHsZ;BY{wUa( z?gjGo9FVX5PD7gsx@P-ivrj$fAHjH9b^D6!-j{(!K8QbL<*089ncd_u{o}FhSW{zcl$}>;1kX5Cx=hcI(_%X z2%r2EjVwDem}g$evt#3-MbO{C%7{i)LYG%q1pR_J&>fnKzPmHbNUUar$V>(1${C;= zmq^n4NuZ9C@+5|({#^{62@aTy*Fs+u%aIbz{f{M5^sG<@33>{sr4v!`niCG)PbmQl zBk5=H2@Rg~h1+}#?5x6}IfI^nNSleB@%Kj6l%60v9zMAsy$FZ8!u3wrvO@=)YKE*? zcEg$lR=&k1AAj3R$ab`2J^s{p$;Ze)k?S8r|3mIG`^b|6)##t0vjLu~M3LnpEXj6g z&B3J40wNL)eHs4A#;5*myAQ9!;!Z8Xc7#{?Nb@@!Y8l|+A;m#jEi>eD@RQKiY>x|`7DxXyFw%G*S|9n%#xp0V7yAJIkJvsHN? z35hwO%L4t#q4-qay1UhBg%<6zowt6U(;#TtXq9XM_NbLwI?x-<_n`cddF+jFl9l3o#zH;xGsQAOh1i!s>JO_? zTrI?vDviaJqsy2EeSGmN<(*@3< zkU?0uK4dooEq`ns?(J3H_`ulG?UUahpg(*V6=it)kuT4`-(I{XI^>fyNls}+d4f`!7O+{H_l8nYk#K_Vy<=U?p8El%`Bdr}>| zh@)%#WnN`*FqKSNvBiqIzjQtoSgH={=7}eg1ZP21W?WZ>kIhgAxQwXaE(<4?K%%!D z7S>D}g%1FKL;39r<^%nFtyGGf6SW{zBOLk|mVtCf+)p^v8fGkNg$qo?-5t=xH>xic$aPw*&WJCX6W# zf@%{lmx%QM)x!&2u#EsM7qiZ@JXY)^k39i>FyQFW;Vdm+Ce$)2#q&&VD}9#}g zTe3`AO$&SXb!f5DvllNCRy$<`y;-frs{igDv?NJ#Gr|XCtvvi%?4uTb3oX2e>LF*Suhee77jNm^->CKX zX{F`um=D!+#0ft0V2|QOPPw9S4RPcRQY6$hVAY5z^*$nS)- zBBWzNwD|YNp&W{v!)TpR?ZgSN6As96N{w--v4=aq-dOZ6T&oJaP8Mbx~IlF8lHUqYrx^(Cu*hFVbc$bEw6SebM<8}<^uFd#?mT(UZIsncVa%q z+Z|qhDi3=J>dScpEwVk!DyjI7ab|&)(OK25nrdi@vFbsGW32pCdX@*h0fd-pg|?Cs z7GV|!QL|9(&+GkavkSQcg6q{vhudiWi*3v6{StPqD}aoaf%hd!I}{GQf7{#wU~-^8 zdAMs!n|Zx2IB6DtW;uAv8y_98b@*-BThHxW|9duYTv=H*H8u$N`-DSe8U#_^@!Kck$_e7|&~a{uHR z<$UHz(r}&a!2DYmS)+tQsr?l`NHWrBbvY2~=-;W0f*qqSjYG}`Lg%plA^vJ0r23Vj zxdnZ0LO4^A(|6%Xfwc0i3cb}z$7>i%-u3V%;zl;tL@?1QOJ6G=0UiB4dt#;;gjdP# z)GKslZ`(o|)7E3xnxE!7U^CA%X$En`v^iatTupZ@tFiQj9)VOUE2x20ESqL3SwsFE zEREOLJYBGQ%+=8qPHUTK>zb{q9D44!u3>gMlY{l;G!H}tV$)AzzTjXrqqA$oxY^0+ zhV~{CmvcS&!_ldkOs76*bElfiF?$eijvfbXFS+z-@UV1_=rJ@OdkOSdg?WiR6f5+F zCJnIF#n33LPgP&>GFgHOd5jtW|2bVZ8NN}>gf$aYA<`xaZf2QgKG1;2-GN)HQ4i2i$Mu`HTIENw(y`9{4bF3fR@svlEv*NQCJP0o ziS%qq2bby<>l)XK_rKI&^QeRlSb#G-c=!)wq?=wARCyGrvWV7izS;|&0$7IQ%~da3 z!yk#wG7HgC!v(g6J7UTrP9j=5jJq8Iy$OdVh1nXfU{bEr!pyX!Cf!74A|Zs-8Y(?z zL&ds-?l|&JqGM|wSRgEj%~E8^Gf@`Qe)cW4=Cd-=_Vff{0iH$vImiO{zN}lJ3pWUn zeBWyTH9X|Kcu6DOqkaGV`R~8~{j87)-Bxw zssqdvhqM=^QCV2js41%tRsw9b#-g*k7WajEK^KNXpC9-h+L*10mWnR0kkAhQ=8Kz5 zx+h@s)M=k+xnqz1@L>3r2)`gYK_VQeTy&GOI}1OOIstW9*@a zZGMs+bw#6#4V+x<_6F@bxh@Boa`5TN%TB%0H_nosH z{&`1;pFhIRQ%yFa>?(=ZMn}VgX&E$VRT`1boQhMTWkN|DkczppY`fg+zAIds@gL9WNKIfsPEFs2s{Dx}T{iCCC z*4VF@qHxxk8?HI>k{1}7j^Bu~GuD8q7`&FN@U8Ni?JB8R^{$?oygI-`+k8y{llfqv zLe5EJGMC}J%e=>V-&t6(HtunHaVG@V7BtK0Sy+uj1HD3?o@GTX;f>vkYkUWL`RM^y zA$?i1y>t6I*B&R=$!62H74WH)a13vZwcGbO$DCc`sq-MNv}Sp77R3>bSZlW9y<@rS zWoL9SAg9OUY1(22q2dGb)~- zSvE?TAjFEZWbS{DFVqAvZ$>znxW%#fjUUrE96bw9n8xJElk2gps|}pxJ9BL8i!e>z_?mu zM|?H3wwVrS;l;;;nj5A1HpcoMLcWJEMzraR4XUFIR#O@)TSd4kd8bK)J!dmKqAk0T zhIJEfxdhw8@g0x(W4aSz3(14_f7EC8UxJ+%Z?Q9h`N>`8<<%#zNY+CUKOHFQ`!`wekh$HQJWM-sY!Of&H>Ei=Dd*N4@|nQh2rj zzqEy4rvY^kudy?Z-!MYY_m3U1=$qD^@O*gUH_!@UrmP9FX(TQAI80}=5GU=!`Y2BF zD924*?n3D4A&&pK28~13gq&z@eJsDVoUyDg{c7ENvctR!{dku=J#Cl#BF?+u z{Kw%xHm%;oWix5s%zC-ZD1#0=vUbTY8Q+t2@$mM7e{}rEvH@o!{_*%H#7C@~ItEZ% z#n2K!>MvZQ8idZFG@E}9SF=w)EsbVKt}eR*@;rFpN%6$O3s17=E+2YbS^|zjT9ofm z4-3u5$;;vI2D9puZK`Y4#XRi1Z}!MNO!{L1X38T0PwGR#)k;lIvL_epKe zx?ofCVQ0p<1jz_{^5XU8pcB?3$?NvZFWObtYKzJ9$cy&<@)*!{lsM~VPv|<@AfBD` zJ9x1%#xFj#5-3R&dit32Vfc}V&oYa!fZ3e9E>+y8P9BVZiQ4iV=TACXQ1Z3#14E^T?kY-+@r6=99x3%EDm6!*>}`(* zBPC~1@@**jL-0SaGO#sud7vKtw;X!1gI_3Kf*0la0lq|Kn;b0l^dz5h-gU01{Jh58 zqOBK3&*=K4Sn4of*t8tSeuu&2Ig^XR4TASXfZ!X@vF5 zq;s}yD%;4Q&T892EuiFc4x2;m@S>gC!go7A4-e)i2Dyk1!lO36`1h&*0oqeCG$=xO zq^~g@TGLEb0QrDEo^2$a*ozC=m^$iHk4LnagUmEWnzw^StgV8$@{xg```Tg0Q4N2j zgX1y(ceqFEX6d@av)Q>vgva~J;O{FnYw`@B*3)JMJ~&2Sj8Mt(a))Q*{e#(5Hs_%+o=p4t^ld(NE*t^!W<_?zZCI5rsQ@$E} z%h~inm6h7;h)|AuYPHET4C1U~Q;*Smoh=Q0iM_W`c^hsVUV>fWZ?{G&djtCVet06I zy!+95cXCc~!8|1nNdO~K&%b!)aq`PV$7fd}{$PY3LQM0>4sUg!G4L|CSB)yNb>XZ^~y0M+L#kWNlH)3upOXY#Tq{J^R=D;mz(0=O&BJCH0_M=#+6=mp+RG}TiJvVyR z7w!}iJ)CV>@XG==V>#CPjPQ^cOFDSkU- zwg2d=@Xr>~Em;_CQwO%Zf_mFLcXv-Ae3bCy-*emUqn^pLV3F^(V_dTO{KAy&H486x z)EALPHt#u@KM=YlQ=ehyf*Y{6EquR-J1&MHoe=T4#{wt8}W-M2|Dch%8R-z=P=u`bY{inKBaffJi8%>@B zRskz8sTv@$VWQ@XE)RnpGq5tU^RH4ld5MKzRjb&K(#}R{f7loBr(@+m2c`Yxt!=Nc zwfVcPuO#?f6i&3_Xx-gk$kd)o{(3$5q!;sF>?xZ*oz3a-+GkPeiOQZKvzD|UWJT)gL2#m{S`JoNm)~T zggeq3#w?$94PKKiJB1H#!!huW00ddSRE~AkmTKpyz-dtS**+6=vEKC-m2ZQu zJ|GDqc}}bKddhJJy?>K~4^}GAD!j?P3~ZFv+qpoEmT%o9p4T$nyS;pEO0OdiGHfer ztrC9U<4E{@k2jepz9ulspNQFsMUB_Mre=~auWzrk6+ZuBIym24A7NrlAjNO-??JDI zM`K-JCnYqtt(ObTL=C0>d-AT-i(Bb}Vugnn+ zz6k#$FRHp{b2cGYLFQAWe_XIbmXax?S>q&o=WL%@xE1=*03j}l*8>_6rAvW`O7k5y znrHJnQTA?~=A@7gk053CHf?;Xv=$nPTYy~5pMUia79Vhkq^5ZIi)wDX*|VXWwHt%? ziQQ|zA|LiEV>4ccRLU`*Njob)!j5(=lGt|I>x8H;H>(JKsn0=^+6#=TjOpvSa-Dqq zy=2eWYJpG8my9vuOqq*ja~!?ihhs4#Atnc7p6z;9E@Qat+{RMpKd>fG%0kWpo9v8UR@Of*V{j$Ly0I+aM$ zk>B=f#zu807Vpv@I;Wt%n6!xA!-uCx157>Way5C^F74p-XlqLVXZ?SU}p6AoP zh!=``22+%wF>wSl@_04T5BrHkVRu6US}3X}x;6*C1PnGk?BACJW5n^c`GE;GXCTq$ z3hG4{)*KzG`7Q8ncyqBB4*m3|ApWL+nKBoAE`R7oXn!9M?r~Pva4y0Q{sOD|XYvc} zmXz)6+?B4`Ip7xHJ+lEv>oIoUK+l5ESMYYG%SwQ+$g>3vu;M!_i)IEqNJ~?+JIbAi zv_|zCaoiY=0j(X$MBzAw(JFM8W|CCQB-HQJ4R+us?_uvKqQWm*;2-!FA}R*@xD7XqUZSCDls+7KWk5T2!}%)lVWB`QDopJ4+M)x; zWhb=Fo(!%ptSnEE#>X+zOWtb1ErQ!M-IyncpY3dzqzQ;+WUfw5Sukxex0_}DtUPxSVNS8E<|PJ6trv9zyT7nXiNel z$vRq?;>#&;^)f4S*4bXo7}K-k=&M_H5JyDPlhI73=SE1lVe{ntKqE%xzzk1+&*MD} z>#Td$7mRLXbDVOTd-jaO-Lv)9o&N4wag{*iNZt(@fpwfO?{b-15TY?V-3Z2l`)6ma zT74^|yGbb2n&m15PkP&Vwc|bLB1GybGP32oaOnDJ@-e9JdfM~fpr>m8gd?kM!7*7I z{07*J;&pwrf)F0_Lm$Xm4=iw?r|LS5irg&t&1EZy$KOoY;TjiXHA<)8cNqACSTEYG`_ zVN&1JQQyQJeBRj%O#@bFR=^_);XaHdzc7N4MW?Ouu;`2FY_*3Fv%2z+<;iS{_RDpU zp|r+HkDb3)gzvGodGOA6SAd(MhV`N#7vzU$S*ulu9ljyVMKcHzluimdLM#RO``>`o*G~#=)lL4L{1K!4}1K^S;m>{ z4B|}>pnn-}zxzCF0(Oa-v};8BEc@*+|LFLtD8DGmm*{51gZW?QGimvS>++E^^IGIg z6&zZ{u5KePlDNE=pg%ztF{-McfzQ#$O>eqi&`&5DnwhD9m z%kXID@KZTSUUvZ89@Xp&=qRia`g(GDxVJg$f4gmNs+0UMS9{65WFgjD8ul#p09paD zBKP(Tcrl}N0^mmVIv@!-ld+PQj`%eA*F}=v_c7dt=$Se)E7zb`{<3N+c?Ln za6fsmQs^Bfjj!$N30>u^bKSoMA4BO*3I`U-ZY_3W8A^2vg!m94W+Q~Q zj}SBN?N8yu@{=oi{o5&ow>=IIou6Leb?9I2$NTp5p^qsR2ru;J{eq~&3%yH!5#ivl zQziI?W_Z(v|J{C*kElkhbghG#k`>TTVFQLKR%jNnSfjzu@l86@`$gxe!wY*+ijuEzXghQ}c9}D==(HZe*J4%E6hk zn9UwPT4sg@7Gt-0Vgj+y@zOvBsj*}Ta%lX(FE+CVl-Mu z4!kI9y%@<1SK~z3ScEM?*va)g?(Z(Rs~B0qn)dfLru3fm-l!)uOvvOxN5H<$SK(4ZuoPc zUPXu{U5(936yvpqmjCoNO(cAC3sCXY2riFrj9DW^!ZQ;U>~l+bhenTgK+Az@lZ*iP zCawk%^R)h+udeoZE|sk*sVPg4SOXXEYPlA@=+$alP);VQu>w*{PN?-piI>XowDngQ zL8_qV6(_WstG#QAdpv}+Vh`QSgkWvi+OkvFX(_*OdGaxM?bA1|aYFaD1J>_d3PO+c zjv&3qy=Q;~=){>GX6g&QOMdYwxFBXCBWlo#ciY!4guW6ka8({` zIR>NX(Ga!DU%Y<@N05R2!fe2I;E!LX_H0AVlXeVjU6lKPH>aRYy|OhC^&JO57c^HgxgqqXK1;-t>14bUH;-C@W+!gwmDU)Zt@!6aLMDfNH}gf>U5>7+Z@vMH9FmY=c7aJq z==DDG*D@|puC!5kq>aoB+UO*7nTt0^iGM9CyWK_wuRxZwV$bTZH>CXCW zl=@D80Gf~fFb1WrR8MZXTDIxA51m%rCmWa*pjXi8M~nC9f}} zH&xD&T^j6bLF01O&7xPRME_bIYDd^+^!%bb;S=&nJ zzryiF`xK0}ZejR(;x8V6jP!m54PUKY3{U7Jds!Gf*=>$I5|0(QAV21+HQlK! zje6#$$w$5FYH*sE?|JH#(2g-XDP5aL+NoUaN+Cv?f8Km5--9uw$Xnc?x{)zw%+grs z+L)!XQ>p&mpYJJr<>HRyotMihfrG5sMty$Gmi#h!UGZ{aep#07T)UcdCY1enXTx{J z-tBwfXJn6iPx-lIcw~h>{ytAxxhiS__Qzow8?G@=tAn5ZNRu8Fh)>VP+93J9dgs)j z4o_G-u?6od%lAi>CAs$C|6b#GUvvrabfx&WH5Q+)_AD&Zlx=XtlzGd_%bs;icFlJf z5bi;LpuD4;fhSo)u+9v6ngqsTZpK$+!$JS97eSQ4O(mWHCnr?NKZ9g~JHl9Oqc`q02Zm<@N5NhB(AqXELgxshCkRsG8ZL9yi@IJh>+J#Zl!oKw$uA=hB zJ@zfWH{>*EiI;9I!j&a^slQTQXg}A@^6(vK<*{;S_W`?yES{M-OE?CP=NZC!ajvqL z0yNq{9T@DTkndSla5J6n6Z;K_XjQurybI71WWwn_I0${J2b?{(OJh$x9(dK2#>&-ofAqZWCg z)R+1eVTXY^N{AP4hj0jy{$&Q%MDk^qXOuwxkN3$|?_$qm1?2yjyo{4?xwXl>ZED+b z%rbU?q*gaWWw-8lK)x9|cx$pS`9F9-{;}umw|pRbJxc_YT@DrXMSLIM4DG_#^C7%&yVw7DJ$Vj*b;gqTCGb_mc6jWYU(YvG?4`m^a#T_u|?Jv|3DKrddX2fw`l8Uye!`;r+5Z{JO3dsZG3IzQ^lHdHyrMTAB}D+6-?)UM5QFZBt{sZ^d{&Cs!L+W7IA6X|M~n$FaQzhiI%rdsK@XnBA@N5lV1;GO2!Su#+wj=vlBrQ8OwVzzD$^nT#QUzNQf4O6 z>hK+JQ0DAoW6w9HMAbEFs}ilz#Y;=zQz>U@@qYPbyXK9&%jXQKn7^X~|67(P>GXM* zAD(@$S_ho*-k2|BV+Aj2EdM2lf~pdGMKEFZ_7FZvmZ&FVF=( zG9{GfU0yM_(UhQ$me}Zo81(^N%_~lGP1k7t!fOI;3ll-jX`g{N z;rETNVP`r_4+<|9BbWAb^3Tj{_8A=0fdsJ8ADjNKgqxl+x}%XhaMXGD9QQVJz&rXu z%<|AkL|+|ogT6{GTRXbW#KHr2fkLPTL;Tz{#tS@GL9C(``i;Fmg;LK5 zP(^kktmEK6-EsAke0_6W@8%Y&PeG;;T_PVE?36t zxPSwx+zMUpQ>Ci{>hy#Fo1PfdDLA}3Py<;pq5X61Oa1wvSgU}-+%Hy;*AetLMS`yb zx)GqYmN|H(phFwon*XDvpsSQ~Rfl=-s}+zPQQOB71(Yi>>tKDu%n>F^e-00YaSCRU z<|yo;C9`+a%4Pd47B&rJnNa#ngywJQw*fIDDv^Ob0IC<|A|*MbyQKzQr`%<1PKU4@RI*=`3~Vz$3dHk`mWtoAE~ z7UAplEcV|c+ZJ;ZVa_b%JGq7FKDOZHf+QbVo7OKfp56l6EEQ}|9ZzHJ(plt5!2VO} zHlxiJnBEo*OjjeO0k4~C8yy%8Og9dBJO|yHecHQQISb{O?#^mwwz8HpvNF8h994J(>$6{@{wkPTA#49ArOqPr`s?yE<49@ifJSg* zhPC<&%6{GBWhY1vbROH9f|kz`=19(th;MNh_=1$@w}D1^8NKw-g?j8Hoq>6jaI8|< zY$O~jR{HZh#?uuy(m=)XdYg;MM;8OlvKz4EzjBx>Vr#53;hb|+z zYhFfzxGZC2z|`@`96lpnJd>g7{3s*#{GmCpn-YE3cDz0x%Seyc1hk%>2ITiFlzX)YKD{)7+^e&U`s7@v;|hznq;cqiM_(R$ zGx5PQg>5Cx`r<`AkYl=LAghSPTl!oij26#3N)jb|9Q*>HOhaK!C9p>s4Et#ruHi|X z&R#szZ9n7-qV^WQy4(@p>s}Tc;CkIF8sRBd6KK5F{J1(eJl435kAx z&DPO=27Uo2GbMhm*HH|u(-#bZV&6Ggm1Qc)_0@NC>`+;B(4eHRDVEPXxjwcG(!|aC zfMKQh*1%gJyz_&GB8(-}sqBC;lIgaTS&Gd}n8?Jfp#h1O_9HR&>S-EC%qHyg{t{pilTzjYKXsu+8c2mkg zaT%nKeGAms6-cLs+{p2yhn@MP`+d&`ruW@O->w37`mS|B8AQ%+DEL1Q*}Xmq^!Ukj zI={Z)Q_qfqa?_4=1w{ouZEmalvhmC#n%pywuvgCTt37PiYIluig{fBYW47mmmzW1X zdI|OgtBR<;US_oLkfdF5?h#cEgYavBrI7wdxv9pDJT(o4UjiS&RnGg$GCID7{xA>T zgTWq2X;@7}uC0N0HC(F;PtyYVT1!h3`i>>Q)r^!*fCn5G_!1K8(yfebOfU(0&0_*| zZ9rdCGZ9@57LwzqC6#jIm1C509El@YypoiLjv5@H>3X_s<7{y7BZPF{&5#Ga-48zb z9()MW8aJ=Eax>vKq0lChLcsevS#?zlu%LtI-};3{NDM!>*DQ<;e(gEx)CCW2t%G)b z1F-J9ASVrnN^Xt!Fq8kLXsSVf{DcEs>Ih*h^uku(PEWU0f~b-Z|JEt7(+)+kdxI(#6hZ)3va>N)zsu)^-_v zI~Jxl?GO%kXYy}5`Lp-9$*w~#rJcprd)l>eOII}=?oQRiw=tiKD~mqbcetC=KY*Qj ztUo%h)wg7T+dI@9$26Pfx*^|_=(({$S>Zo4nYa5MGkCjQEcycaUt1;PE`T=JiTe5m=G=a|enfeO#ga$V-^ z;BS7UnKC1|dmDCh(5T^6L~~`gdgC_ZR9g@TV8zDg@-FKOW~v@o@VXpTk)py~M&4ze z=Ya(-Jc$N>X_%b9;DH4lqu+KWv?tq>vqIR>-RoDu$~sL5g`#f`X?s&yjFGj6QY)ml zMe7jARde?>FrE=_#Z|=TCfu*BFngk3*HsvE^%eD=Cp=LVu@%}wOoggSWlpLy>}M;Y z?_|cUCapED>WSWw(&qK_a9n4=p+Q9_z*ZwrJ)`9;L_%|4b z@zN!yd&8kkH`yaB_`;FW|MdM)POsk~)B?>suN~0}n=0^-pWD}}XSI;`oVBm=y$;vG zYmWOmyBXef#lXjcnw0XZJfp=DAMuvqQ1~WKp3R}ZOTMx)rN#jx=4WGt8iuesJ*#i4+In91(eVp&NSVIwar3%1j6@&G&`JdRWHos^r8XG%Bk-#rv zCS9;;;142pineWRZU$CbzH2HW;yT#GzC(d&to#&$sKcm&?7>pd8m z6Jn(i9gLry(IP)Hy&jxY5@d4*7J9}2+5O-= zv{@k6JvnQa9GJ8VUt^6(*!O(RJ8D5QEeSL*zH3#gelc$eg&O)+`E$1FA)#xPm$7N^ z7CIL_SDOE@^nnTIBPinW%Puh5nmgcCB;49hyNw%7ZBzUnyI z`U}}1GFJ?-pI_0z&udci&*f+Ajk2Nn9+{i>ioBuuOiyznWT=Kwz1|mIk>}Vqd44XZ z7h^pL-+U(TEAs4S2K&tML6v=6mAL{o!uD|$W}qqYRf*f6H&bO1_@nEjQys=SyT1qA z<x{V|zv01PpmptJ#c>kP?9cRsgNh)Y-k&RlK zpQcLTlhE>j%!XR9+IdgV>Pdc{$-FB-?FY^50QPgqp6}msjN0vQ=mF8^cga&%Ocbk- z=fB0*qu+3f1ZQgY&7L2JU{}hifp5_}lJQ1EPBJyS4t62$)3fC!sUKdGIM8wyt=-g4 z`!G(;E(M%T14eR|NA9_JE#1Eb-o)Tl9-1_x13uw8kW49PH1~&IyIJD%Ub3^F zxFd)fw1^qILi2trALnwFtEZ(A(1jsAaVZZo_VU*n;Pb~C{W^It>5`wQH&oSOXOI1u zYi7a@K{e?g%nEr1)8LyUz>9BlqLg!?3uj(1AN%znuQw)uaI><7TGI-YP!#l)SN%QN@Gac~%iFmLlZ%|)F zBkm;ZK$6dAQmol)7o-%HA`aCgf~qB;tNzD941sWBWGAqB#Qx>8|m4%Jz5P*)q! zj>5j8WR)IMvtGy-=1F(MgPO??Ed#`&M;oukjPTkGLj}nhSL6M(P6M=c<_2|j+F9*d z(%wAWtKrx0L(-Kn3*Qwo-$@HX>)AZyY39As5k4JY3X{xjWGl4H%md_!24vV*YP#$Zqa96;>Id*o%jz7uuta?An-du*#C0@whj{TL&;6JiC`Biy9A)dWdTfUk;`#=&P*toTd$o@FN#@Ir8 zzK?pezAba#jA-&eP-O`FJCeGjT0U<~ko9I&_Ye5x@WBmPVI0sNj;Wljc>Ul4)1=orSaBN0>mMPJb|Eg4 z^%Ec%xWjpTT8zkdTeZbM9A3JY{{&y^6+DjCTBOTY zQGURq!CpYj#GgR2TkWnc|DaK4uijxSn;`29%W%{fDsWU80yuI8V|luFMY&EWgr(gL zSl7qS_BQfSE=XUFSdVVHvWd6aHZ#^k-lEM%H%IuZWH~2__#152gk8Wi6EAK4?;S*^ zCD&fi=~2S(%NKjd^8XIXe$2MJL4%n~Re?6ssoIxmxR!&k@VL7@S2zwoWM4oFrrMu_ zkpncc5Eka^r}^d$pEd=iv|lpL30q?Dh z+IOnQA$C1cd*cEd9XYTNC_eI)^gv#Zf7_PSNLVym(pnR)-dd0l(3u_LwE^d?w-LoY zYqT=IxoS^onW#fK&)-^bsl-rau~xkeop-)t#kzcGV+!-q+AnUQnp~`U%i-FR0!~V> z_*(5(&Mbmnu&d-@H&H_H^knUK`0LM7MU<7$AgG!sbk&70p`wT5jLnt$0`W)sO` zx_K4Q8?aNx!}3l=-?@f(kHSMP%wdhy(6!wGKX+cw?mt)OZ*d6V6e)(hcG`ieZ)&@% z%v(~cS8rKfZLUqNT3x%mYH#hXDx$TBqg8B#;$ za+=aF%IS!Hqc{us^$^mFs=sJiFvP zQ*fmhSKubY%6ceI0j_*6Ux{TWuhSJ9uAJ{P0zE+L>%pCc{DZ*mraR+s*et)Hg;>KkUnt)A#$VYYk;1S<>}tXn9TYwSy?#h-cqHIvVLd zq@$4TMLH7c9;E3=clD(qKT%Lp-_ABKbP;dhXvVP*haboLI6lO20>__moW^ku$KP=< z9K$%22L&z)M;s0Vj?p-*I0|sg#4!iQeK;25Sc$_1d>EDJ0Ea8}&F;$*%kcHb%3t3m z(?WF;|2*X2OsgS`IJfvrz*UB*CJ(Iz_i2~44K0o?WkE++PW6sMgCtNbD@o z%C(eYCCh(X8kaW%G+Yd`c7Fsf)I*RU?u4J57r0+74zqk`RQCyWcE|d4dVWkti{oT0 zN?O!n8M0{MZ)9daBtHGm!6BL={~+v0=j+qSLei)%;dOe212@l$+oQg8m&VTO-zl`F}Rk zRaSctE!FOp3d;$pB2o6jgUt^=vZEPJeSC*%f{`R@OSJo&S0Ofvl>YQS$8=cT{PqSv zK@r@Ch|XQt>G$OIfaHe#$Z`B?LUiQ|T-haG*=3{tQ=>L-g==Hy#{D&@l_~Ks-iGE7 zuv%a_bZ9u{=wE8di}#L1vK;bkF1ske<=6wihJ@#?05>LS^@FRoOZOSKOZVFBK;u(b zTAbiVus;@&_MzBXy1K$rLDw%kzo}@hcxM%zTdT?~>sHYYav8s4gqGFH-g4pc>eU-9 z8|nVKs^*Q~$Y(88*!65_5!P1*2c}8S7doo{i7TSbT3rrn>3WPP9Z)NW2mHf?j|PwH z1Dp$3cM|dG+cti__KpOWgUod^WQ1c_oUFOtQkKESoM|pgtG(#d9|flw&zZL^UE+6F z+S?5qZGOWhWBVy-2(d`FfQDD*8FPRv1xX{xKL z%a;=E+W9<-%QBj2Y=guxl@gUXdBYJ?T6K0BCJ}TD$tja zxA2Lj0clo3T1CAWi>u`Yt?&>_sXwt)TbEW5(J;c5P+RJVatTZ)__PYE_E?lB!4>7z z9s3hFJkHY7n(Bf)cLO8|zgSmPd|4&ris`N?P11mGc(PAvi>a&er)`X~V$NW_@k7@< z*3lDr6B~^2@kVWaj7u4s>{UW%kHe^gtU}iy zgmf-QAxygZLyopB2Sz`i|90>5+{lKuDndCsSZb&n=sS6>ZCe*;q}H;Vj5l4|cR8{wNR6hJ;#cd@#bBP}!-8Ii2smvSsEdqMY*FrFjvcoob6t)vANb(t}PR zl;GjB)xo$>f}78Z32-J2VrlEmng-62=T75&tw6d}M0gU4|5A;5;d+E`kE45Q+qR!l zTWvKljPK+@YqiO=R$EPhTbZQ|0;9(>Ny-@)!;D?;N^UMCl;_EJV+1JPlkU!+ISP#F zB_Y1HsG(I6Bx}^W^9wwSdC-I#66`$cn^26WY#z{9)7zuG3be}!+cYh{N?JQ&EHfjo zsb4dHx}B`ms)4~|Ur(}i!g@+TKij(6;B7ztG-tK;>>L~ou6JyYdF?~63^Nvta)J_pUM+;fbn*Cxfso5bjgqbQk>9QXtv&NDIq> zm!>%^&INkbYp@s^i^xZ(rBZ%$%Up5HfowMYR+Rg!w8;tN7@@>!Y~ll-!;cx5oNmr+ zVlQ@42~Ls9;4E5L>g0Kf8MmfwRq(cD$5CmQ@g#b-wG7_ui(6L_m-wCWeQUwgQd2Peseb6$;2WgzaTdOE0 z5MxuARNw~3_bW&aW>)!>A)-@;Iqo=Y0+@YspcP)XS2TgqIf^c0jwbN4X__2mS9)mA z+^r9CIfiapZAbKE^*aq&{q_nxu|7i9h6+LYib7EDFTp)!=m>E1wa0K?k&IHWxBmAM z(?Z+i5|iQeHlk;2zcYDkzx|iU`#;K?gL`+%!}%{^x1JH!3mt!ST+q-TGLH^Y&6A<= zMLUIr4(jb0#s;?x^OyAG*#1xswJNJWlvQ#`p*0+vcS#XxUaLJeuirUs(Nho3 zi?nk&OM*PJKkG-Y+#jIww@XH|GC+P5CH!2bb$74!PJNRCB)h#iS( zU&)dGDL+KJ^q&jX4vb%YgnDcTpO-1OIF@RB<*nX_cs@I#YYo2EV>zn8<2gd$i5vs< zy<9rw+WNodLX9Iy{;F~%u$Xi7JypKhfe{`>wl=8k4_RBTa(O3v0Xlja{!Ng3a8dNm z(K*Ua4SAxOcvED^n4=E7)%!DElO4W7qwtH?snDax#F_9L8^`5hw3!V3Tx?wZD2y$7 z`q#1_8>9!QGmWzFf5KNe*-EsC0tisi4cbt2gG-ESP=-SA3ZQWsU57qfKPCWAzSvB; zZT~Oj8ICE9F(LY5^!3m;h4iiT4dK$UdNyz&eO&&y2~Y_FY1WuAJFvub*1 zPg`JfYsLnqw2g2Z+h`|>>57GH1>>06A{Vfv$hIFq#mz--dnT!V(( z1X$6Nl%5MEBJMpOign9h;Mt`5v|yzCbaLlPJe`QA*W&4|cv^SoX;VC6mC;J0#}`cU z>G6D$TVI#p!I-vTj2-(za#X=GI)5Hyn{kjjibzKwEeeeA3OTkwtZ)A9mW)G7#-SzS z(UJ)PTKj2rw+7|CQ&9`8R{@?F)7e&*?k4KCZI#9s;URl9gL#y>xPMQv#>eShXOPw^(S;fx zqq)E-^jWw%F0moXx7V5|_ehUMe>&1r)!tTS6dzT=Dzrn-j-3-i(cVd@dt_&XccC*e z6zN;yp9u|2wAX$uC&9qZosIA~TNSnvXOwqu4t7p=F(eMtW~78@5AD+Mrz5>N@Ci}j zno62FBN{uNQCzMQvK>>vK?)cLIr5-liiLjAeq>ehhSfx6h>PhjZcpHG70eZn#jBl)QHOwz?CwL4i z71<-|(&g`*(n;f`&7bB|S`)gUHQ^)K(2er;6!!=ZcX_7Z+m_(R%u}g4;=HL;4n~B= zWdVG`>vf`5BYl`ZiFBc?n0fp2(-; zfyQJC3ZOLAw<*n2usP9K6FVn+U6p3XN$CUF4ac5rEo(AT>R;D^nZkh z?=>hCp$MPQJ4%u2=KMenl4ZLF&t#v4g)kO?#FqPZ??Nu2{wnbQK&{v^rJNb3r4nB2 zS;&5IW|Cx^;cSKE$&!gPs%IAJHx|bj9GN&Wa9D7dahPxzag3gkj4wg5T0VFoR z(NjkD^%>5rt^*c6&Vy&vK5bnBC_IBp9aMWp%>TSK4J)D0ofuNPGgm=s=$v+`76jJ+Aekto0GW&Q@VQm80n%86x=`%^xkwtG``d#ZStM z3TWKC>6uIR;%6=`kxPxM7eaAVqB*W%5=I8K0ns!uYbi2_TAn)Gc5!y0?2r z39F%HqKFVt@CiyhZeY(smymcoVV~@&K(V& zBJd2GE~q2}dOmqmgjdlU$;ZH(b^e`eA0*&AUmf^bh=MOV#58WH+dx)u| zq7PKk%nzXJI|$7jj&V3<;jkTSD_aiR{a8<#KMR;-7D+LlsPF=wBG$$DbZo;-l~k;w z+4$UyM0ciyh}RyXr=kM6w^vz3=P$9!0w>w1z`nwT6h^fdD;dTQaR^a?{B{M~tVqgH zbUr<|-p-xoEj|w15l||%9s^?k{3{=SJKvhy`O^3%P@j;qIGqFJb7nIvMM@%7On;M$XFkhudqbB-<7%~2rBKZX*}}iV>)Qp{|+{Tv|6Pz_mE|6bg!2;l*N0~nRf`!*k+2E z($8lQB@Bre%R8GXJ*8WO^61JamV^Imb;+JMdA7v{)Sf#zN8*k{r^SvI&N%}ApU}m6 z=lP?tj;g`?&BV@TV3j?YQlT!%UEUxo$u0mG-8~5-qjW5 z@k@$>M`lfuiZ-Rm^d9YTk>2;)>FG$6Vqp8uMEDi~aZiZSd#PLl+uXef*x!1T5s5v> zede#Hi2T>$*l)Y&>&ymUIw3&xh85b|$M_MR<)S4NzLU^a z;1jH)J5x)dJfE$EWvE~0ReSWTtSid5ytdk)3(-4cP*-zzv{!{10NE1%rk^QFp|Ylm z^MNBQoog$@%F7kQr@3uawyZe-Czz21s=i?`!I%TOozL0a-wR*!!FF2HNdDqFxLc|y zhkaAyZt11+v(j_NqZ-djPUkOSnX3~c8@$k#me;*2&EnpbMD7fb9d(Vw(d7l);Eff~ zU4A7?N)ozvVwb6Dw_=BhKAq=q!!9Lcg=C3OXWBz?`cu9d~hptI*nL!IhHK|=T zNcw`rwM)qJYuhA;Capo><9U|8Zpd!kmNBXa0a$PXTa-qX{uly6!D{VP=st96aniX zYLhD9hA)pB5};GC_Wnw86r?#WuT1mfN!y7&rx4l1nP2emnYDdshSa|sh>$&l`l)H*7>PtHP(pEeClIkc)wPhY%cS0#tyu>uGtaM z`+UUwS)?PeiCjE`VN0ewapvto)767FT}6h1$~%JyrT)@T&wV|6?j|5 zaYbM}i#!MK5Voe1-UY8IX*oxCq`vYibfv`K^7G~CkjBE&r|0JhkjyEqs=yK02oVL? zf;8HbjW4hl9^5K{w~h{c1>L4l(E}V69)2d<2S=e^iNH3^%-_}?>s=)tF`yTWqcJ}4 z1&q(<(>N0ve641YZ*;KC^9l0IAQ=YDf!eLx%9PNHrKP6n(v*hca>z0a3%J&G17YYuS|Gjfyml zw&Scc!S<8Q(e1y%haU|u`#Q3vDuL(lL*g+&!Y)F{H_g^ei>8CSF| zTcPUMO;+`gchdj0KmNDN|1baeUoZc+0evr8zZs1IaQGc(qx@rRbe?642?;;Bvt|oPTj_c9h~-Py6BF;2c1;{|oQMP#o6B zRya+-f}hVy&IxKn)G8{zq+df?0Gx9;H&&F=eZt7#-alMQy4p;(dXRfxDkZ$ok^cle!qjhn_Hca;OOX!mg5Qyt!CoBB zN+qvApvC|TzMCZY+uhM<4}-RBptu%(1uE#I6WDKI z&(CG8K`7Zttnl-it?8^ zW-(9Ko;8J7^)@M>J)y5yjBB13DxDJV6v{bEP5D=_Q%q4I9t6&J!lK|r`E*$2#Rgj| z=}w+sz*m#EQ{Q>hXtvWWzf-nU z(r35G5hPrQJol#aj`d$+@SwDPlFpQK;9V)h_B4DHe?3wQ4HeLF>*X=L1IWCtW#Vk} z10eysL^3oNC9oLOTXbXe4p=>f>K)F>KxESEvW2dQsU{}y&l~uBWnN8DFD%ps2mWIa zc9U68qPKLKRv;m8+PDyJ()PkCy&n2Hy%AUkOQ4yY(Y>(!1z@Z3TKM8b4jW*HmY?dV zoBjQ%FJSk|!7g)|m}*A+Qq+gMq?9|8*-%dj-f(zO8+z^gNKWC3gPn-dm1<6A{{@Rh zV?JTYki}U+LKOSpoOXOv;9*F;>G}e!hPq=PP(c5=Pj$84{A&TX<40gwNl* zU5X-zoJ&-&o=V5FT0ED,}#MCbGzJS)}twe?XA9#|_l79GJ#qy%lVy-MTS?f-pc zBkX`yvMb#h_&A=H9O|j?8q_Q1v#CG{=h($6WfmVie_^87E^&JxH;6pY>*Ry7FA^{N zBE9BPK~+&`cPGQFMc zsKS4>1~H$be+Sz5wnY@}@rs?JSuSE`*jY^#+QdKm`bw59$Iy6z{^!2n_rc2)nC+k- z7mH~vWJyKO{ft$2(o>GA-O$G$m7XvXU#js$_ueJMvU8nkQQLN+mOPpi2&}6(z2riV z%5eIq^oX9z=Gc8zeYI|l612!PV*}bTyNb@1*xj1g(;Hq}=TB>mXhrn2p27>KrNn%z z|LEW&#%V8g9VbA0HhOJ=d1Y2r3vq$r;w8w~u$rx2z zrLlF?I|)_GunPAhCNb_gk4k&EUjs$#1>l_Rv0;U2Jo2!DrxsJ+X~1<;uSGThcj>&*{~;s-kqwX$?rf>`YLvjs zKMc>nznv-fQ)?_zgxs2UoYb1Jb^XBqr}l86h`Mmj_s?~Hjgs7<7-K>HT!)I zm!IZ^2J(siftQDtw$s?u2D2b_UCA6h0%TX5^@HGte_wHDJ(z>I$aNYZ&7>1*pfg6y zhOS$(r9AhNbSXgy)k&XD;;fs4gl*!^e;$2Kdhi*x6*3J^8qY=8chs!KMR9P@*gjkGeGpSE9_l8^v>W)ZOa9H3wC z4jh)Aavtv0#ZCoJxg4?;T?Ez&?Lgnz{w#k9IKF|t)xf0+VAL+>1_s!mO}=U~U+X)L z>*aLa272xp1$-R2XOe>S%q-mX<8Fn2eFfF8(xJ%HTZ)ZP{6|OP;my)jbJwIS&HCUVVd!8t5F6Dr|9B@vrXvAJxd`X+NSJGDtyr$=g=V+6$3Zvk?{I+yF z54}3L*mlF8?z`;wf?qtmT^X^$z$EDEE0PGT7=HplRZXGP?!TZoUpNSNCDY;@ugn zZ%E;;^{;V|hDINVfVb)eL%hVt)=R7OwXlWb^Yw@WN_b`pAE7V-_rR^_cjm(1sHm=p z3$F1idslJUe!P{}qfh+T$xh*F-~4O*m~ih!8x0LZ?N zahX{2@|G|2V#UaSVarPRE2*&N8__ph!!QsTg#C19EE@^WT`sFPsGMXR|7~yzsFvpn zc2@}Fb;pEEK9h%!X{2ZbwwN#;^n6fb=0buQ^)!ZSNV=#KSmB>5D72+iX0TmD9G<|v zCF!i7t8fx$9;P+4E*o3}eU+>s<67KJc-(ehF7>MVx=qwjYyzSYXXbM3?8O?y*(?8D*|bd?Aq`2?f3Aswlq5qBj6q%< zl%J_z4qMaZtLI!at?iU-++0U3FgWN=_&PLruBjJ0A=mlM+!TA9|A#HGL*aGx?Uj7{ z$##?p7yTscE`K#HR>hzG`nElQz38p5caoy$vQ80`r$PMP#g2G?gYXK8gTnW_4$hv6GVR3SV=13t^Iw#$f?al1W0vN9{%regVqMf|A;RGs}nC zq*B`v*eGi{zbR8(p08*fOgDOqoL4?{#<;U#u{!1Eh^#7jDczP0qov-}=n+^>_Bg`r z>y*F1=lK2fn*)v`mGKQL{0Tt*)dDp}t0H-!mA!SI=ENVX)sQszw8ps_rDfRP&~|ud zX{bLb%FF3E?3^6iTMhh9lbUhG@2^};d5i(X%|jkz5ca;5!&Ne6YClIyK;?vQ1A zFM{sh^QT>q0CLuffZp4UFHbgk$=!dDzjy*!b!_)){ujDk30S(+k5sbQp|zC9I+F~O5?DCmx6!I6Q5*R=V(k>g5fvDcGH{I zv`>d@JK`tr5g^&-A=!@Yit)w6^Q4y7`4At+Wdybj5SJ~=ozP#^J@p^p~X;#V%!f($}}GMSW~a_Q_fl z8mT0o(Gi1Km@%Hl?{(ZG>=#`EdZ*HHZQzaTF@+eb#yH$4EH{;*#uc@k$dhZ4OUzBtx1_qBl~ z*L7ZA=ELv?nGP0m2HdI3+n2T)^%?!0Z@Anmh+ogB-h$b1a>gxIm~k7Cn$lFW%F zaJpra*;9y?9DJ6d*^XipdKUDbe3s6#d%`(0dtNU3HmDi@4frqn6!P)AmimVqSFR~; zsPjP~XzbSx=h_S(<7}@qBl%4+bp>46wyHx? zX93BK{!(?=G=+`owwv}!?{l`YDa_E_AsOTLN*{1>W{V^plo+Csc zK*1Lo2w3Rfueubb@W>5zfjbpbP}XydELt-RuC>cjh3v%6pd+y)N4(nSV1$91EeefenH}v`?6)S*c)W?oz~2X56zmcwcpo5*%6y zpDW(aw)Rjx%k9zZm%eiNO(+plFJ-+zXhG19q_Bgx!tEFy_`@+8NiQFa5p^CVxGOiX zv=&~^#jZ{9+=|5;135znd%1|?SDuFCbH$6(+l^(jnX}6PFZ&wbtY{>dUx9>-WuO&2o+3-LHz2d1fWC!%jc^J zv4I;CRG~jy-L^S0V84=v>uO+abIevnytKV)B`G>2oY__wcs&7L_Diz)YKbOO?8%{0{y9QZ%f;%lRlB_PC z?Hha_~bsroE@K3VJL=+=hKj3hN#+`YBFzyJ#)lFF(;!X)XOV zq!Y{2m7rLEgP5CqP(Yu{@ARNernUYrT5F_wJze3<)IO>!kGkF^DN*(ptyFRwW){`5 z`&o>lh!@ay!n-NMz8mhDQK*&6W-a}%zqd-?=ihhj-POKUSJBDgW;U z%W_KXp${v$36p{LC- zMo<(4K7weKBt#1idp82*ZKiftIA*h3@9~A8 z1@|PeNm6Zlt)zg%6F+(HB*lba@P?xV>vg3`ZPE08fS59k!@Olpx$HOgY64cPVMO?W zoQDO@(--D3F6#BhG8aZR*Pv&%VPhG!L~ozP-fTKiw&4)pt5XS=XRCgPO?D>VntH(L zmzKvLl$M$i`=WRc(zd~LecRwD<5ol4pb=+g+hRj^ku?Z8NM4Vc?_+or#7K|d^P zOzGwYh`^xi{Xom@NP_&o1lsx-*tBsLwHXn9xOXA_=o|1!N?FsZ-q$y=9#Y?F@9_ftrAU2_Q&ZVm47|$m_6Hx8@M0&~eiB$XSC(^IuR1Lu2 z*&lxH@cCjH7BGxD5eXu8^dcD^frrHAVO5z#M zk71KO&|_RmeTS}|ma--xqJfGqO0p*D;r~b1_v8AwNr-r}{zR$^D8!tF?jj#@aF!{^ zGgADMf4zsC^)ykKfe>hs&BQ@I=DK8rs?yD6T0on*_T zeL9s(J@f%&A>+nS@1=tFf!2@BK93$9L6mO}R+h=E>bzhvVuq5Wnb3>xLfJH%)BGgy z%VF!z(*InW%O93eFI%<0-k>i4%+JAieJrp(VB^7Nb<*#6{AMHluJfYfC8^{= zpx~Oa#Uf@`kcW(AEqutZS1yGYG}fjE3)#!(Uo=sBZgdxoYG_?>?dAq=k)~6BUDan# z*=I*2i$dT!Xc2|MU_y_*C#@W7Vzay9YipP*|DTm*!uvVI@qPwKg|OSj$XbHOz!k>9bsr-}lS3B<63)rwq0Mc8z{l>r#hs(owM{|;a6(<>qhK+2GEIaAwaJ*lZ zJrbDZ&zLbXPL};qim6LHb`mSiNy+A%23qi|oBN=zDg{dCz`z58Kb76&{{$}qh*6N- ze2QO-WBIyxzxU~QNOjk3DW08zaY1qk@&S(xxuhjPdybeF0eSPum5AVTL$SDFYtd}= z?Oa&@<_r&PCG5^uOFjz6H>cJR(p?4{*5vpt#b}}JzfdQ2DC3f#Y$~D_j|h%yr#H|J zePiI+!oYGDPm!o!)xhB=Vvs303!>R-AGC_it;!4~@PpxQ_X6+;}CqpAB! zQr4?|BfFEK*E^xg4w?_VB<=(eBAA<8v*LtUcrwT(5l}r_3sw%dNod z|Hn-y>~h9^@DQwZqq~%5ao;lW%0TJOhhVR!>YB3;(Mx$H>h{o0`<1waCdi8nRlvEd z$?jY>@x?$~=Uvc+{;o>dS%~!CoKq)G2ra;wse0+erGfh=+F4&s@;7hdO0Zhp=|Y-Q zy$4snulewsX8iM3A7?wN|9G_)RQS1?li%2{SS(FN9E-0R+4;w-m*EflWVIG&KWyFv zTK^Q@Z)bn5X#qcwAm{tI+J40>pJmn9uf*fb&fc&28_LO%uU@W>=(JxME1##<{PAie z-gBVlu8V)X8ileOYL2s`C}F((+#5B{i`KRC4;aek?HAw+`P(7%4A$y5YIaK#b9X}? zL2EGRUc?7VD7KW=BR9=+e%Q=jyAG*CqQk-Wmo9qq>hT9w70tY?`TZ}yra z_LAJn9?HJgt0; zSLxy!GQIO!_=czhiU!*O(i~9jBE1p55$x(MUl7Aqcd5q>1pODR zjx5-`)RvECPoMc3Uguv+$8(wEl;JbT&43$)|EGb-L;v^S|6ct6I2X8TMRaAa?KA1j z%+I7w9H((C#Sy^q*O?zYHsi6+q|b5wF^=OnI_;lH_ZEL9eSq`BINqB%v}(qx&!mGm ze+S3DnVU*!zW?mqM4L%0G57T?yS7K%bb&jTomIU?nMQ=J=~Mt>rZsi}m*Ycv8sh9AJv3p-$WI`sl<6=5|lbRC9P%Fgbo zqIJl?hHe$ZGHrU5=mWmBd1?CMR_ynAnjjzI^OS)cM?5g}>@2hDWyzRlKp%gS2W~tb znt#Cno8pAx=nEv5;rfzqmv{QsOq7=Zi#^d3!~W}R_$^=Dx*no<($_-!r5GnL^GxaN z$ulg3uXV-hcpJ2f3wVY!hOkRi?T{XMH9Y1+&Me>?+6_k5dA2`vNLo3iBXsyGw?Nq= z`wh&tvx`o8epc-%sgt|a=K&_=J^lW74uJ}yv2s#=epZ%|9X{KR=Vuij0{^doR_-(T zZAtJi@X0#27UXnd%kX?|>vAi!HeM(zp0m1MA4SMW8$1Dgc z>{DkxT&$c#tL;82110_{fY_awyN3r+PQK_(EnNY-log&l@L19f-ePg)K~L0Nn(sSk zw5%%dl{%YOP4ZnRwXB}(TeYfr^%UQQRhBh{zE!K6*G%orE8<`o21o-YC&Pp>M4ZW^17F*wTt%=Uy4Y~(OL=d8h%(H z<6q9<#=H*8tF7=xh!qROQK1`})Q)wC`aMRDD547{;Op`fhsaTc{+v7{gp~e_+P_xo z#Ch|1Q;FEK&OL|rvCBbz@@6eJ@m#P&dhZw5DE>_ykO%7e$GHD)JG6YvPLv!ieV1XCxTdQ9y1ruyw#RR+vq{WyLxbrH7pL&~k7?D=>F}1t{^QbnBb>;4kBNheapJy?NxRDD4B%~F<%0GB-}`%~a9cv! z;!I(_bA+$?RW5P5du~E6QdSI~P?f0nb7Sukiy*CZ@JiD%b`Q8lN8Y2$=CmEDobI1q zX=x)l;S{#2d$NHdQBP#gb-qwJ*>J*7Tq$vZQ^gg2vY|W=tK%u`KI9{-<$IX=j5;)h z3HT3=uXLdA)-~b={}%l8?}R$plajWMbd&Fx5lfzP&zWrCClyX1zLJnD|ItGzpz~#f z*#C^vvaikqeReYOuoECZx<0Uf2)0(Hl;sl{gk{HK z4dmO|BN2xPylj8pyuR@cZv0iq9AI7PpUFa9lMTkQNo-6fm-$Lcm~USNK6Xian7d88 z!^^@?Zw`EesrHv)ZMNol>PKjR$JoSMviCsL8_8nZ79h4M7FVUKOfRiwVAVAA4tA#ko8?tAgkIgspVOi2##6jS;Cs}EtI(~ zsRXt(Q$d~f50u{EO#&z>(lT>(OW3V5RBArF6+W1p<_In2vL*yLM`@b_oL`<8Z!xl8 zbuIPhZ*@4rXmxliVp#iHjqKSjd%M+v-a|AHSTcboS^k6`zWKCLr`4M9G`!UEvskGV z)^rTpI3pLbLtAmHX4Vx`zPo5~VAhocr1v9DMLG{@4pI?m64D~1Baz;XbUe~&NEaiW zjC48DJftN^Cm_v7ir6(*-aRcYjV&`TZ|?bEXNZ_ExQASSN{vV}N&UDE-h zD~&zetqzeCMzP;`z|?Yc;I$#(Tn9}aAv*&0T4CL!663jm7t9*)P5kd^uSgG7I^qu) z!8!l?;8Eae#wj%&mGImMV+?Iso5|9y^RiVm-s6FV!o>I%o|%To6T|3p&pzK{29pmQzeT!h%Fpb9I zw*n&e|W3!%Bm zvTXxRKNIW654Ut7aFu4-VcwIh@L#1_61I1Nr73XGhpM<^WUsaL53kDWJVw`oL+}e3 zaz?ujOOfT#h_tx0JWf2;S}(>oDzRtW+tV&3l^<_SZETm6<*{|qo)R&w(Zu%NLX?Ni z`Z_*fVzoC3S51)>5m07n0#RA2z#c?lUx+9e3Xa~3Cvm9t+}MUF&tSR@{sj#Yk<&0@ zxW+6tVQ{9$?u#vt^=RRppqu`_7}t12Olgd4jA@K$Ol(YO)HZ4wM>H5*y80+r5~6I~ zAIh)Tkv`sP3TQfcYeHb=DZv^a$g$oXObp#+9f|lVT5ldK?eauzLqTYsH7#(~Y734I zX?BhewN=34FjD8r3i;C$>Ju9>pjo5HfV0`#-H~-8fBg4ccT8QNQ-hs`G8Pyc6~*ZXG!|DqJ2Gg ziG(ho2}CwcY$yMqIPYxuF#{=O{4ay?O-DdCx73h*K4c=`tv%_>EA(vEP%cIz2YG_9 ziRQJpMu6o!$9C2bQvA}_`}>Yw(KWq_x&K;CE@GzUVr+c?pOx7GNcrI_T?{=;1MC~` z3fMh&`@WJ`xj->k>j}4re1$p4_tW7chP5|1{dEiWMVB-eD@abj1UuR13Kk+Zu%@?= z^HrFjYqK}qDV1vk#@QgvOWu_Seg4+~O)t8vQ79V7rzuzbm08{Ufsn|myZEuNgxG=T zyiHqbZE2Im*X}4|^+B)zRR=lop3GgRvzIuG|64~2TujG6dr;Az>5IP;u-=c4$gxMB@7 zS9c=d@va2eT;U5Ie1MI=jdtYI#0Tiv@;lE$>O{|Kn^KBnU^7R#`Np5IIi2DDngjeh zoq58(D}Ba+?ej-MX`qE%dImQC}+SqhQT< zeB{p8q>9jM(x!t~`uKtIjnPdO$JoZZn+SC&t1-5T?Ehbr_Lb|KApJXTZ5+|`nsm^{ zHyTjCO=`|mXPy8*D|g+O(q1R(bzIR{%zg&Ssa*b!*6N5R@|YM~O(SxFu~EaZt}=n2pmaD6*Fjh-unb@ll^s5z#6+BO!;pCFsiJWP@0Lde zis1FAoi$d?Y~tZvYjMD0_02HiRZ`%0en@!yDd-8Vk>n^bzQ~Yu(-PpwcL|z~$lKSa z!3Q&%?dYKy#<640yPL=YFdGyaeEWGFTPfo;%z*AR8c$?{s+up~na@Ucd!-0yRI)G{ zMzYRxUid`!fF4etlIn=`kKQ;%zM~Ii{(BXdjpJIMG$7wC3tN|{Wb2YF(B`99eHYzH zbC5q!8rt$%-|=|8hqNvkJ*2&MOT0c!S$v7NxDl`iQtI-kVz(sd6(X*!$%BSljXbI! z^Cx!bfmdmN; zza_5-e8O^j>AXP^b^kmISRYYKfdM041GIEmMh#Dmqho}500=k9po}8-g^3ukvm@S$FX(i zOR*ESOX)J@)B-8t=W$yNC#26!9J~L6cGRKNL0rGe8c_%T<10lkttr!bmPjU!_ND1B zc_agB158nt_fq+Mg^A=2PO%WXK79LFdY4n)zs9~qJsW%AIwIxXp@`K1lx{ofcF5rsXnWpLnAxr7Bak0v<~yKivd zv%x~Nfatzc(q1#gOWbRw>tFul`aAOVcg&rV!M0rWR7dQ))Nj`ZB8Rj`=EH`lfKNxv zY;K2!CEud@eFyvVWr1`^VIK?}l}b3ODOU$<2^(Q^E@#Ivr%Lfmq&I^l-kKE}>3I{l zV49q`An_bNAsSwu3laZfYgZP=*g}4!XA%34F1>%Gdos&A7c1k47Vz^$daH(=hkm;T zJoi_MHum0qXJvT?XsrO&3p=elkwy_3Y5d32H=-KBkg16q^DHW6t4m>%C zuUa}BqhY)zx~^SHUHBij`>ET(Pisi&E=~9O{7)j5*9*fW@7MC6sVTux=+&X?I|qA#-# zwyK|-!f*TBls>ukrdz+O@>X&=cJ{aGk(<4F zKKto63H{Ye?)e`r|L?7()}{ZC*7?vQWM${AKIsUzaQip^OO0eyrRJ(|efC!EuH?qs z*DQOS9U^0G2UvZC_T3i90#La=vVK2HKrSaLLgCpU+ z6IT7PMtIvN@^Q>~mdl(V9uObC zpz*5F@;OzSoY}#Vn0x<;2+G(&xbHje%&3Lz!ufyAsJlADGiu8jnyDRukv?DL3dn6T zY)z1HZF4-LRw9ZdSx02EhT?a>FHj_x(|ojLZs^Umn& zlt*9ZPe$KzIB+Jc;p>4f!|7`k#x{hFY&o9?7QFRj%7Em z6CXyFK03;AJA&0INoxWgBC9@|?yHgKr(K?tc5~u|Q_{Wi`Mu_t3#gUs6~~PMTJ!fM z9Ciy&qB+H<*eUE(?&LEQm>+R=Adk$XT1^nU%lNVQKCAxpA0x&8gb(ltaSD9HQ*kyD zXOQS*@`$$Gio2skeymrFMtnPdY-9*At;A~Fe^?BLCW(IoLd7HC(8<=R7*tZ$B&%QJ zQvu7GX2ybkX z&70_Kvsm}~9A2fdqpckWZ$3m#I;#1---LQjvT5xF(US^e7}-ACi6 z*#$Gg!Jn>73;0ozg>&cFgM;C3n8};_U2m-Y*D0|Ah?$S^Kl&CYe{(`yDfOq7sVQj1 zoBO|g^TNMrj*9?|qK4NuAl`5S_g9_>?pDfAe*+$TLL^i^`!nG{XBwDdqTBIZ=Kt*f zO;;K)2{qkqWg0NaFBTRry~9<+T7jpuZuGHG0|N?Ddj6BZ1}$;P#>)c@$od3-Kqjr_ zy@?DWz{#XGf5o+)4a!5EGD6e*X%Oo;>+itBPf?CUWU|c{9s|Zo;*H6kFPvy1i%!Yc zwxDj*;4K5rQk_p@L}t|i$tsv!Wt03THmu^-T5X$7i8p}R>2HCphF;w5hSjK|RT!cB z<Lwr))0Q*u@39`L! zPFzZ7;>JARvWl#B#D^pKA~6TCSf%xL??fg{N&8O3~C+a&9cn7^;>w%YF>I>i-!`=g6o9NUmL^NQlSi5Hi zFGL<1pl=1(Djc9V?=0R%-u^uUk*Zt_|(`DlINgj<(Z*Our1X zg-T^!>f$D_el~O8x}CrfSNno%t;kH#ATQYkeQb7SZRG_^cZVk+}rAiR0lny%Cu^NJz-XPE$m0xUdBCIb%-& za@6T3hK&btg=C?>Hw}4=40t>4f(5_K|2C90m`O=Tw~UpI&GU`hG#^X@?=qJovj$bf zY(I|d5GqR%q617i7`MkYB1YGVIHAO_JkIP(MZR%+_c6o`Uc{AM88}~N#d}HgO_r{p zf?sg3H5+{td|EFUgs;ySF~Y$UA#9h*Z4z9-#6mxh#;Q39LQfNeUcJ`70U3nR^8YUI z>^IV{Rpp1WFE0j1NX(&XVpLiIEV4X9%_nahjNCV9-I#)Fv#E*5vC9PJ7O}lY zAIwgJ4n!j2@NSF%W8fo7DYg2j9a#9e!aK;$K?H0JX)(QvcwJu)!0l2jESBG~W(co^ zZuls^zOttjUUm2GYZL2JYQAm%c5}AMbP`${jN8DbLGM_TC}`t!enU_OTe3i@JcZ2S z)C6SrssbkP&yfN=A{Eca2-|x}iA#5?49bNwF@k3~uSJdlElT6e2w|X8K1qM{9Z6e{ z;$bTP`BKVc;=rESRI_kylbf&(%{iRkT)IDX3UEv%$Ui{L8%iTNP}FOj&!p)jRFoQL z>Zfsiyt1tZT!xxgp+!XzuV_qHHeLjdITqPBDCfFqowF)F2iMS4e^xn%TFXOUS|X&M z#dwp^1O8|F=05Y}W}WW|Ut&-;Nf$U!nb&UHl!7sz;zk@eNJa_v>xy8;aE$k0s2_|x zcPou-#2ywA4lyzVEpujtN-zx)%K^peqI?JCKsPgE-J-SFBi;?>sW#XLF30Y|r+lwf zmcpmH!e^_b(hNp^iR;nG7P^O)6A2;4G^k$SNHi+x216nlNt&i>t|sXRmg`3 zU|1{76q4bgsgN_NLxk=4&ZK4veykFwuqr_#juyfm2DT(PpcGS>Q0kJA4k;(lV28#-aq^B#DFKmEsq`Zt1rnwqwxw z_kd-k!>01*+t@(XrW7C006b}C!I+~A6<2|?_-RaN^PwcZ0eNJJl`(t| zVp4MCO*}ck@iTn&U^^g>shZI17~|m4GBdjppw^*38qe!f_ipBPSfF{51I3NKzrl>% z08|&A;veG6V+JF0pa@TF&lHoTyhrg6ShVmahVc(TzwUgc0!(0ufmNlozzUG3OnEBH zg;}oH&KKp1k@p9w7Z;ZfM&5$TPsu8gvKAIIwzd|Phgb@=R*gsH9a0(-O4AsRnyt{& zd8-C68wT7w3*g7asP2qG7ECDor!eiC!H2?ov8A`?k@JI+3btHv+pD*T&leU$O*F}) z4kp2`L492vnjzC3Fu{%sL(g*TekRpu358dO!)t6i$9gi$#(933Hy(d!_?zGvdtl^S z@FJpoYELMrc*#EGkn5uuCj7it#oIBG&IIDh zl$wsbV7KI<&H;+}qxyK^g|n}T46|YTYw&($c;%THsOQ9X(xglbDnp}@-E=vUe8bS5 z(YO%!{)|Rg2HdWwILrSeOD+5>7l0qi7 zRNj0bw`SY>Be$-Vm#EuYN-$0}E#-fR#18&doU!LH*hQFKlvl=rJy7Q1JTozWLN|NN z3XD6#O^WC-mLZ+=)UdGJ;E?|wMxsMeYUCZIi5CYWYr#tm9H z_;|7EYd|deg_OzyUhY|f6#{Z%g?ZPqq?yB98Y>hIPzJ<|-usa$kSYATn^+pMnIkzL zi8o}*ZgXiXM!%l!Yz8<$j;w`uuJ05L4$2?72fzGJcZX)HXh6=Y33eD+%uv4*PW8^` z^+43@cjV6PSwo7xgmM`NlnXl@ZCFjKsKfRbfpTGBC6I-!lCX3Ne>NgYKu zpKhM~1IFs{7`u{s9!Fgu+HM^w^ut0MVnL?O2GS`pA>;Sm;w|`fr0`9bbq#(?FqRG# zMqzdwBTO2wy5?LiV}b3no64Xq73e9OdpX15$*}?@;l$@~|DvlOC3td-_*7avIZ4>R z6#J8osu1sq4bHjz&pCBDi2?5#;JKH25X;HF{8xNx!FB>%%@{VQun?ExnuSJTRS($& zr3)z|)hHD8;2pA7@CnfKE;jE_sr`5(quVehnfYZ;v#FznMZoObi2M$o*A-=-``#97 zrZHo@t+_x#yo&88CTEF{e$65@jx=VQ;%luV4@DO%wzumRiBR%Lu|x_xG1ShW-8J zB}{*L@sG!wbm~Bg!rcE`Cp5T(QH+tUB$G{(O;u0&Ye2$OU0Z6$CYpy+P-yg3SL)g)3VVC0cKWeKBvjV}!gAze zZ51cXP)R-UXbZ>m=hZOo=NqMdxQ&mm+18T8_W*IG*a0mtbyAb2p{Fj^rD!5f*AK!~ zEb>{v>&lK-@k4eiJy87Wm5nb6+!ItZCxGKj_{LF4u^KenXqq99FWyj+1TF^cNf0<@qJDe z^#HvPKx8som{k>Jm(vSv(sxId##?ekgE0~NN61538RCb+-x1wT4Jy1S`>zrItU7ch zdvkK&T)Wa6J%(bq7UA7NJg;5JYdmqmEEg+zZ@M3a=jInNUoRG9TICoe;?QP-=lb%j`sC_=#Y*E3!F>_?1P)?ce|UIWRliT^2gY#^g_2G0Ut0rUmt zZy+$}t#XvSnl00_u;1JX%@;!n-=aZV#_@Pdn)RQoa&6o2pLsK4p zJg7N73eR!@(9orR#anT2W@2>`6I!hqCT#B^OJo5rgkvJeQ%n6trrMIaKN(ht%MCsG zJ;PrZ@w^ZoylQoQDc00e3_1~hJQZ+#Uw{SNz3dKRVf0%nQGXXA^}r624Zy%6nbMQ) z1*?z83VXyYakxxuCYxlKpy&e5v(5S+Yk|&Uz%Z|N&k=s#P1XWsJA@;-w}`DtYGuom z7^5kw>VW+XaU+pc|z3fEw=wY*i9YM&`+a-+dvp7PuGW&&Oj8FHctlUJsdp%V#@P=_$dO zkX>Jb`KOQ{4!!Q-9oHky>x`AO#0h6Z7TZET&k{YKlu_b^f1XvP--}U5o?hr@EF`E@-jO~~HoJoaJ?&Lh2=kzZC^CvVHQgeYZV4t5U z#B|;dc2Ue+9?~Gmf)$;ujzoSpm?zzfV$(dl5zwjuCW+3_370zW`hT6F6LPy8(ittd zOFH!NwZ~|I4Y03nk8Rww& zW@1LI=+WVQ-TAiew)fp6^$oBf-RTFp^WVo9`NhH_&Ya+vC=v9zEx@3rut%yMl3>P+@v96)KQ6qc0uL1DRrvlo zGxB`U-VoGh(|kL{Z!;3%rQ3>6@;7aTZ$}Tm9Bp@=ren!xHB2xe6SwzQ6pwoc^J1)U z0G3N8G)Sl|PBwoC3&9SLA}NJfyK2ZQU|CjZ^EFi_`wA;HzLd%oU(_z(V4bQJU|Ky3 z-s`C;u6;OXxUdb@uW@P-IO8a7ze>+4=L(PVUN2$J_eneM5ZbG1npcUwYbQw-M;s;Eh#c^q3uJg1>~c zI-10sOtJ}R{A?1lt%_iyq-8n>R`Nnv`;%d>{&T9etx1&Ib#2h-$ymfESI}EpEg>If zOT4^yftQyMGS%%}K>eK*m$PS|@qnT7sEo~gIJXJjAR9)V1>h*Sm`u-n5Ee1A9?WZ~ z#HbydYnjz9-3hIGIm@Od2zq1)k#Eb4c*C_D)c>uRW#p+^UqXe6`hbkF$bu;wKW`Vm zsV?yNc7qM^3&Rj!tz2}i|18=1o#f+-SL7xE=jVjQ`(iGk&5A1!zx1-h1oi2(oN0|%d6T(C_PjQ zLy*_MQ)H(Tx@aXk8~!gldM%hKnr)a3G=dv_*@ZF1i@Xim@8FeSrrX0@kGvu(F{?cD z?S3XEG>$`lGRAe%nRw+I)mGEIdjmT$UNbgQL7e2sx}9~Q5K_)k%}#Rc6c102?mak6 zfial&9-h8a+=DS5cut!FeQGdr^Tt-u|CeE8x9YL=3Dr^&GV$yGLi6khVRRQU^B)`* zV_Cr~gijUM2V)wHb=>`RzKY^ZZLD|=oqs8 zGX`vke$qP{E*MVd!?$J=_TOe%Ab$akOovY^g57A3`S8-;ifkE(TAby`@R{Twtd(0l z{6MD9jXM24ULnjoLmUe99%f4Y!9U&1ze>L?F#xMdbvhmqIfbCRU8lFX1r~3st!;_1 zDUl7+ zZ>!{F=K?p(a7qtZ8k68_FTq&E*t=9|r;dnvdo=$grB!J&2ac3>D@L3mFQ_i0lva!f zMLEC6r-l*??bTyVmBi7yf^22Py6|Uk6JHzoV9CdNq}1B)-f(0U-779&+f?SGd-Z_P zlg?j+o@Wv2a7`vHCon8XzjY$dj%@5gMcm2%D)()5pV&-NEm{f2g7HviA{(a&sDq;7 zjo;{x{CG_#uKB4H<%`~<72jR$KlM>}i)K5U`8WK3@Efy=0V5%mSbZ8?f$(!jB6r^+ z3Pl)C+_HF5_#T#GN2mc1em#9{WUkYuc zeweTu@scSSsr)EhVFJ!SJfDv01%pMms5jh*e0Y;FPYMo~de)tOHBjqt(G^qVOUhF8 z168m2;ulhle7@4K@VL0${N+kjqkO8Y?_)(7`E)bOoTtzhLy?EY?791$sz&njf;(Vv z9FH~rWPczUAN>(GL%E0a{>jh!Ov}(esDR~AyS@Bj^aVst>!bZ4w$$6IK;K`0=aG9t z5xc0Ump8UtVHZyg&}x4S*0Ku&;OYdTe4g}1r1LBdt%;JVQC8r5?HtUzDlYfJQpdR} z^?tqOQsm~qKG)t_4&DIyti4qq;l3$#seJT~-qr=UlMopgRKKRE*ITmrOUU7rH!Zlj zmTQ8ak-;8#oe=$g`PN9g&d*@gOqskPC=yAL7-`)x;%gw8?HsZSl%6(e3~6#Ju`XvC zGBDm);oW-@`54)P7WyZNhFx4eh!hfLwEw?SosC5&Hm8!AoJ2 zFFL(6__p|w{V=edhk>^)%6?n?(4LoV$|a7Fx5d9=I}ysBq|`t;`Z-{}A7Aci#um|I)MujYB;&+G@B0Wz^9;OK{MI&)rCa+~Pl2;e5 z)ffv`<9Vkh`U=5ZQn-p#F%sKnmVV}9g2}vkEo)b=*0pDq_P7eyDjMnNWo6rZ=W8e4 zZoM|C^?trmohj=(#ud3}&Cu-HVr+KOJAM}LnDZ~VdJvz4j!wnf%A{Tdt-G4D^xUTQ zsGY6!e_b079(5UJULn#vsBAutNZ-pDP4c0qXf93kw^o81b?6MB8k3;0%viP=Yx2+4 zYNa}BuBuz9S@^KCZl&qh1Eq+8W)7^1whWVy(-m_&9&ra_Mt$T%*N&Fsq8o^?mB@JL9d;>9%Q>Hb@%u&eLG5Q_Ph%=Jyk?6)KsYg}$)jkBrt1bRT7skv$nX5f*+p9l0!)%-KAZMAQWP-dCT+p69W zXEDz?oi6nYLgcYqy7~=JUz4A7y1?{k=?@3PeKkN;jfD!r2IEnq^|ugPa?4VGP5aHDnBkA+kMwnS^KK5+tB#+Ra$5N!@ zowHT2{_`;w%@f}5WP(*-C)PGqi&l5FXsOR=OF?E^0nhqJBIgj9Z8F&eWVTH}W*b!3 z_rh*kgnDIVKudsW2n4n@&m*UeS_4Q(Yrs&dqwKaEtXw|0365`fU(H$ZdWEgTtN1} zc+jBt0xeivw^DnRg66uuX<|cO>G>Gg& z{Kt)T&N>`#XHS^6RmFtvMij7yp;(yyHAQpW0i|%CbmwNbCny7!;Ka(;ZJAh4vG&(( zlkq9DbI?(45;=SB5n46b@LvI35m2Fsk0fj7T;Nh`Tdzi*xbA{=p|Fc!)c)VUxvu9! z-xK9AcwF_h%9$&Sb4(uRj;e%UbZ>p_OQG0Uk86&pwsixz)|ptfHv0mb>T&J``+8H= zg_`3E-O2Cjy4(}CnW|jd3aY-VZF0X}TjYMURvS#K>vWgaC0D&(SA^dh-Q%|vx-Zs^ zaPLMRDE2kiswXJ@Kfn6BCHLL#AM_rnf8Z^^7fH3G-c8ZRCDNNp(xD$l{YznheKmAhsJ^}F$A%zbsr#-(7)Hv2eVN{zDV^DW2@ z^jxUJZ+1l^=2AOj(R=!8FKmg<&Q_P~DH<#Fx5r5uC6!OXq64PmuS%!uALxlfi& zb6dch?Q}7iLq8hO>?VBM9=9H7%FX@8H}QP=hk4B(ne+{QvkN6O_<@#u%rwlOhrtzX=pzrvWfdfD2ZWW|fiR%bn>hAnrDd)W2&4M>ctUj-D@5-j#&NR+Kb5#u7-8R92fQ69OH+gK5>t$ z$>jhF=1Qbt@ZR9~yvwjj7&D%{T-ZYXTOo4)jc3z_cD^OWeucV_Ha@!=bDy+l+NNdNP;skR7R<#y46RhWV0_SnA-Ka1DuRwD>P`Fk?^WFn|#1!Ch zKgNGW-vU`HdhS8-x8@x=iU9CO68`et)XnGHDm_PtldB1}T8*ntw3kU5#M;0vvD;j- zW-0QPp|=Pd{iSU>;rTOJQq-|Y91gT0N+S6t(r_k|YKN!kQfJf}P@menjgT4gz*q2$ zXYfB4UOHplj%;m2P5A14+qiyrZb=EADpBLxTVf4nwL5Ox)O~o?0{aR0L-&=;fK{>t zHY1I01sE$!%Cg%DFF6JXlE)=X>EjtA&s*UsDwn>MXHfZb+tr~04$sPfGlFZbX+%9S z7W#!SZwssF7c~@U4Twu3v(>HWtJT2wVyN_)Fe=MDmm~LGmw6R^HL?#euB$`$%09zL zGY|cS@UM)JRt4QOAnt~1&b#Pb{2JsuXW;WWBg&bgnD<3x$5KT{IEgVBXS&`8L-QBm zMZ<|xpX-ywepb3w(r-vH)w(v!Z8p~B*t_##cU-%M>qvP#Z*M6sb-Q-BmVsGo^SzV$ zov{tI$HGb6F=$$RW@6XQQ*Rb_-_C znp(!vSVh;qcx{%8YdQ`NjT)}O^~!>!rmw_LhbU()H60Uonpe5hmWz?sZS}#873FzEo;^XySz#_*L>Tk!Lz{X&DB#Me3vIROUh)Ndy zBJP|%B$pAgW(Hq^IFY(TExd~QURAmXWm_d(liuoGxc6|5)@((t;#J2)c?<5s%@eIH z9#;dbawChowXAaP#nwyCo#J?d)p^dDirCvocH}JV$G!>XS-xU$ELz+$N3nCSOEzn- z(^Rpd0-W2{ebpspD}4LP@_e3av8eGnW3dxk_PwqXCMZ{xl}Ng~@&H9@9}vzXcMN*X zu;OBc`+BK-*}`X4#iig!P#Tf3Pb-XUC=#|wh*UT7-HaKFg|R^Bc}tB@`QBCa6=qmM z9a@AJIuCqpbv4#>L6_CQydfqSjJ1WeVA#U8(a>1ig>4hIhZ~G_g>`R;W^7vwjdk>l zP`hO2_>#93Z1Zk|N-Mrkz^@bS`?kTJ*vx@7T^^9Xw(6HwpZb6zsK%DAU3mcNdIwgy ztiSZQX7I=QShY%cqqn5AskX+a8lQc6epRz;e@Lm$nfobzYj*B~r{LTpLxRf(e$QBu zmmGs*rb@@e{?{?q+H;Rc^SjkkwXduU^~Ku28)#F5!;HoVE9#B#QVbZf_mu&83H=c6 zc70}@1(z5UZO;G7TN_lSEQtB`N^o*O)1@#|JrN=JOA z)SdL!MxS-f!W3vVa{jS1x8bpbJPUJrQe_j3H8GC!QpGR3&tij^4@>0e@*v2{V z8BP*n&VGtD=gS$u44y*U#VqjS+a4y}NfRi+n;UN?+{1Xj6Q7sekv#V65e!?FF}Z8iSFe6PAV^B2}N=S@2rWQtr;9Vh`*n% zjcDcg7SM7n^;F;L$QwM~S~;I;ivt$+OL2AmGvdAYEgzo`;BPtpw&Sk=e=F+a z8*B{})n+?6*PP#+;LKQHX9c~?2)i4GH?)0U zx|03d26c+&Oo(CU^u@BW319}ia6uNZ`XxJLSZZ3rwfh7C;9dZ?TdVRZ&5``1vHf{JsMR5?PG$f24pJ&9rxUzp-EG} z4daC}bDMKptukv{)ovV-;`;%dbS#bm_kQ?l|4`s+c8m9!fvZVnvFcRrNcYH&AVbrx zBh1ZaO@M_GE23{1%I5R~_X~IROsrP~JE0pKJAw^@Pq_k6H0d`Uwecp|ne2I5a z^IIy3`M5%P5?3*sq+E<_As39C_rYGHeY1|xd1S#1t)>}IE_ul33Nc+V=hKldN29u? z8nFOvQjkiL(oXmjrW(qK_#8=Bf-i;6WP~eQnqi5em1%d2_uF&ZsJ^Owcs@jZqVvN) zx9k)XBvym7TMXXjQsVq=UZrY&j8^;HuNI;G*^jS8tAm$B)s)o03Ie zgTdQX+gOWO&r;*jHmn@=O@!me`lgVcAF+icV+|o6F*2ge$^`55!Pf^DF z8{+GB@@%gROa#g(7SRXRlm40w(UW3~24D}^(ta)-S%P3S-J)y8`*I*cA#A@nu|Dlc zx;JH0V%tGJfc3Hq2tbYVO9em?om=k3&Cv}bg5c>@V;CLuXaxrqx^Bu z5Sg;e(Esd@ougJoZAu=X5;3+}0VUqaeRwC)?+!$?(wm~!twqU=?Y46hy(y*Xo{>I^ ztxohd7t=Lwn3WQ*!`J||1JjXc+n|=>R~Swf#r5e%7RPpJJHLy^tE04ABM)?m&tt7#}klzI# zL?*lrS)Jo=dmwU!%ClG<@i?AIZ=4I?#6+)0+?zUq&NL^qQyg$<8?~}=$PZ-V=^1jw z)Ox}pE~x~UCqsLUM|WKt#c+L9><8kX*`<|B4GCcRBoqPtVm5HF@;(&5z}e`l4jNUD z5yAjt8|eoUuipqw#{U>y$3BI zMm0LH1EhTFHuX~-s*xvAZ%l{WbgG^+p4uUHF-gt&;FmrQMk8D?6A`^9J5@@YzZ|0o z>At*h!;H^~O-apTgoS6KZ`b|sL~oHR>1a+r0@J1m?NrV#6?+OL z!U)k^xwJiHQ!e#o^h0XlvH(}QUDqVfa0r7E&RbulZo-qAbzY3_hW%gxNZB;8DG~g4nm?kS zt5m>At;Ra%1N;wt_lQ*)48Vs)-<|lr+S-tu+ozH=uc$QMb}!cZUU;-jxnB595_7fw zPF$C~S!?Rd!m%3@z3Qf8;@WucH4bBv3V4X<`fKFpWMg}_v_0D~3)|V!cD7>* zw&zOQa~+egy+GPt;7G&vJ<|3)4hy#PrR{vjaBMG^wwF7GVjG-XxPF1dfbEsi_DY8q z+fHfQ>5yZ4wY0q&aa4@MzVt@jYgZy;Zqm2JBlO(#)GTyv7K;C8_9@2lUCl0d=t$Rk ze~m`#*2(HA>VA1(VpE=L1*bzBEr7K`tx16x=?qr)xxHHSg>{F3|>El>-$Jv;(7&^N{RD_$iD}&llM4h@CLAQhoBv+54Q3b z{uyoc*_-d~&wc}QAN)42z47wDCQF{(JGKk_xYHO5Vf3DL&3Bnf{NkrmWBAMP+ttE) z`P}4fJy4ZVw-7nqgdXEui-R(UEbDdWfhy}7D1X(PYLok!LgUdxux#|mBUHPgS-2;r zv+bH1Dp+Z<=4{oewwf;RyutglAw`~|Z*#ZRB=*k*+jWDR=GSA0<(^h96rS&D^lhjk zMGuxEjx3p9D>Qbp!ARtXn{=EN<18WJ2~Cz+*R5KAGBCG2q=H%x@+Im~ipNxeSk&E* zcFL;T-{7y6{2x10-xd@0m@wa_1~ig_vCPK!kHCLmV19^P8Zfpu!W!+tICA?ch@%w! z@@N0K$`{gAz5q_z&ME}U4d`7$rFcky-lYz>fCQ+ej)T=}hX-T=SOA6j3L*7f+)1`f;yTsC+Sc|0sTptXIZDR|`d$ckuapVsU3i zpOR4Vqs@za$h68p9&3dyxmvUtnbaGR**DoK>WLS@>;B)zPVm{1)3AcD8E-@;NXLY5 z4BkE%oStrhPtvR4IonV^7Hmqh-Ex<_i``Ei_U|LF-0H>po0}9>^HmD6gjw0dCwnP; z;WBG?&s*C?#ieVAFf*JQ8H6pr>1}cn_pjpXFrCx#%r= z;T(=3U2|6gWBpr!#aCZxXioqWk|Q9`G(+_`Ggu9@kvw&|@JM$ueEt>}ty3Drx7?3y z+=45WttWQPmF)NtvxGRPmY)>2v$KSMp8?tl>clu|eOxeYJ*n-)Fk1YNWk_v@Wk_vj zC_~)YDNIyrhp-Mz+9!d}ze)dYaLx{>Aue^v!JQ#@Gw}AtnJunZzCnBgw&N1av0s!A z>vzw;CqS7f!-d_Vg0Ba@>agfAFfSO9Qxqq&L38KRo22+$e{DSfNvqQ}TzEl*1&yo^ zLR=Ve4wW2u$kWgVjw3~-SifbBJhK6_`3d7i+_Eq)j@gY|K7W~ zm6?oVrXMw=n(+oKZKcnMG3A%SC08kD3N5Y5aA>YepB!`${xtxUyFb|idIt1p7bBWQHT_Lka z8CyvUIf&-DC8>3TMq4UXYw^LmLfm%O>S|CVqqn;EV; zUrTXdc@_r@-R1Dj%jK(LeAb%2EzIP9LGL&k(-jv(-)B!Xe0=0vZRFz~{ULlD%*~AO zv74eISQc&<&sxH2Pf7|KZ5;X`gC5VR{6evdvAkgH< zzLQ&%g6*&rWL87)0CaWr{wM+dVIc668LF5z1duw^RMFyNS zyCVq<5CJiN&kvDB*Xi9IlHQ&60>{zYd(*9%lpQ|cwp*>`taV>G>d<=R3iI%*VE8*< zzGNZL_KZC6eT2WELTxI8-$&*^FP&{N2``=vB5OsiF!(tj$m-lcwlnjj(%Px^HoO{& zRY8XZV>hk3)Ed-493A_3@0-k?WUYOcbgb#dtEfSC>V^$(w9-mMemClG@|g7{>z$}Q zwM^Fcw2W(zL3Q%|k%;qA9V+7eCa97aFe2XDOLdecUFixKx2cApR-kx)6dN3dc*7{X zXE&m_caERdtM2=~2G?Lxq;q-(*y%FVrUDw9^zKrC(?c02S^jez@DgYb&|aRd`pI#e z_eJz2c2W)EYAgf2kHQ$nx|8^KTzErv zOMgc(@nDmJ3F~>snSFVed#A{C?1cwZZ(%1;zQlf9@pvnkEIU`gPx-W4Zb7?8R?237 zw)Iay$;hooR{sXP3v%T3-6fUvp@A)!10Dk|WITVaa-{Gyj&}J~p#{1H@QC~n_J!e1 zgnl+_Gjy`vB4v?;QKIXX1vMI%ENC^w7zaWAXo0w?EYtAabk67vqR zI6La6W2P*m`F8YYSnHOm)F*S=Wv&F*@zSNGx(WM_>MSuqi!ZvTp;Q%&Zs~nXOW7dl z9v7`Es$@cb)-9d^F0WM-at=Z-a_iB0@l5W@byFO5IsJipG0nWBmCZ07Em~JtSudWm z?#P*ORLgg{n%B*Q3e=~oeFOcWx|}rZYhKrcBksC=MDsfPd-g+&WlHLjTxK+TW%jyU zPjP>fpkZ=vJZ21T+?7yA()h|45Vr0g&&^b(X&uIRw0SCb6dUJD;nlu9m%q zXbYbz%I=bfZZLz9!-ICTG^L$2=K?!*pjsPrPFMELS6;3mJQC|TP<`3`GCW|n-a|${ z=4n!IjSq~rg5QJnVSVHiACgt)9D|34J1`$KhqfnTYow9dGqEX~)P6D#pBkS=L+j=G0@89+0@ z=YbYC=USwaT3*#CNso+u4H*Y4V_7ad0cnh^7Qzfor1wC~ajX$1gg2gBRQ=@3Hzvn3}KeR%j;Afs<#!vUt zou-`1b$wnCsAYj|n3e&ay=-RU1V86`ep@4W_-3D(rkEDPstl(N!plH)O(^r__6)wb zVlWavco6l$X1!JI$3^OIZTN zr%z$UOsvg~h$kGwfAEY+TYJpsOWDlx$a;_RDWrcFS==CofY=_2_Bh|~2a*q7qGe3_ z9Dgu%sLwR7fnOQG8LD_ZA)hhBsT16NBEMr~~nU+^X*`8Oh76D@0 zJ-Mo^>RYEYl3J-{5{JC5oUs1=hJ6(Q;}m`ncAftBt@Tjnb;9=}v^DO}VqLksEy zYHvoy1eXz(x@eEK)VaV?C*6VNKk+|Nld{h_=Zg zkFb{aMC~3S5=YrFP>EqD$o<;>jy3OG>3B>H4I@@Vcy+SU#7N_;yX=T~Fe6+zvY^H?jF zXLPGBpORFIpCkUkDb~DPs!8t3>b<$7XZ}zw+RBtkC08}WCd&Qnlt(7YdZ|}GFggh%i+sZhSC6JGN9a04 zk*WT#i@5={=uKIcYvvCRgvAlUU(Tq(t)6B)92$&EBi;tJ8@1T^&7UC_LG5p`Fh#8% zV8u9oA@h9(THq2T+S?PS)mLU$DEid$gQ8{6-})HssOxptX+6#eHL&czcR06_o%pm{ z6*|qWDVruHV&+>8eQeDDcbRS6lJlD`V&b9t*1#UPo{B!v%AhqaJk5AN7a0cMEnlxO zxQf>-ovWEpT)e7ljtSQ-_6=OV+?u2AnsfR0nN2x(x7__*!QztQWx-wInPbJjU3`7} z)mGHmQ2uHwo_CFQKzVhls5ba=*q&hVv>@&uW*bxBUunuoKF(g*xULpkGmh%`F+dg& zFUfCi8W+(S$3=hYYU?@^a(6B-%55FEdUZptwFLYd6XLoCC&&Z((BSN?VsZx}9a?ho`vC7c*vOu?kkipj{qh&4@3+0x@DNy7gSNeg!ZFF}5uKhvAN4 z|D$1r&5DtWl2WJp*a3wl795f4AUHaLBc<<4U2L#4cWJ@m3k_*KYEp4X_ObBVWP(HL zQs>LGVzH4wWrXl-@6fzWz{l**Fa}=^4MFx}bpMuKgS6kDp~wCQxH#K!>G&slwRuUT zB9*zqwF&I6E0Ws=u7v5@AATdxJAwSN+xxCettx--$9j8Ki?U4}mX20G^^x@3t$s|B zwJdkoqBQ<1<5H1xkAQ)v9#D$%J_c-9om_PZet~yjgpl=L`?=M$Uyc2f|7-s-96#tn zen{_ca_Jg_>iMfbmioqwL%T|M6wm8-|9VV6GjG?b-J&6XsxL|S{n0QVgK!2H3rRiJ59TZnO+knNrn)}D(X^N>a z=x0jVu7jeJ!CaR=FZs=!nBHGhJe|W_HUed{9B7toA+d_hN`ak07KR~Xsf(=Wokzie zFh;&Z(V*N#D6*Yy*w|Op`&lSTxr@17%viEr_wk#9^2Q~YEw_c9hVSv&^aoCpcc``Y zH+f5j>$15}cI*aMiz`$^=oqeVN#dNCg-}>^8$axeja^|Jb^X~}DW(iw(YPLn8;%Ph zkC^;PQ~YjMTWyEEBdf*PR`n9l=Y7yJaPWt!RE@-6(|O}uZMc>q7KG7G%netq%-b79 zwc80%$C%r;u$Dd0d{Z{M8KCDp4^`8Qez zBR?QJgvL_pdq;rVn&qPRQSV|soY3865Y%z3R{<8d;bz1^mL9<83*y&_lC?538McY> z@;@-YYk_t+AujJ|eAJW&_Io}N83DohKc9C58FtI{b#V+6008*ObmUJ9gZ1&wcZ>9HlA}=%6YDREDdHb~e>doXh1drao<#Je))VC6PVI~ZAb z?S64W_U!h>{d4fNfm?E3-NplnLuzbu)|>h7!%szI@OLoQKb3zZ_Pe)=7wxZa>f6LL z>_UF)0w^j|9x^8ky-uUQ36Vt8FPPwPSXofykTTOT*1H;cvYa0TLgJ&$ZLsUC?e*eT zg?`jRsLeXyjQC?f5j46p=s8M7C~biZ8sG*sH?7 zDSOgj(+2398Q-WxC&iP9hH6gqNIu`K)2-66^y{f$cykkc3CH1U_z1WtM)=Y_VPo0G z1Z9f+xbeWo6xnfO-^LS0AdF#msN2wnqO%g@3gzsR3#I3&I<2e# zS984*6eUdG@07{??uVZTZfxDg){WtfP}p>9TWNuE(Mc#{qTbU_%PZtUoSf;~D*t+; zWh1x4x2|H0$s^E)<` zLu=@3>_cyw@_9kyMyxPl>kWb}f^o(0Ttg$T|KlyJXSrr3ZM8qKg0-y-&}>EZr(I^; z&ZHIkTScc~m#FM$#YnSt-i)J8{&Qm^>@E(q=52*)x&c0``c`pyxu%^(hK6MUMmFtd zE`z9L;N8<|2N*+(ICM`{-3NVImTa&IU8GC$5He`(%wcFDe~qht!I#XFflq{q8|8oI z+Z=|h_`%47H-1M)*^gk|4n_z^_nHJ_cQLY+!Oc(KO=Ss2Qwalv32Ty zw+;<78t)PhF{7ECgOTdN;k0&`zpNtaBcNQOR&gatUId>Yt3gdwAM4W~lB6j_lx4=^ z3(1A*3!It(EACG5>r5K)*(`7;Vc*eK8v7T|)BBZJgU-SFQrT}u4rZRT&Ga*A|MEj; z(>`FNnc-Dzy^S$?!1yZu5AzZ8>GyVeLI>U=>@nyT|M@6Be?J&`^Jw~aB4S0gs;C8? z#BUKV*r%OBDa*&f^8LCRt6UA0Pjx{J{}kQ()9_&*ZDEGdTnzs*9Nqg~*eUJ37=9=$ z?^AO?QJ2%q5?xcX)9+T?9di);Sx0hCpf3B(WzftE6j)H}@4|ON-|f=(TNs-#U$LoD zj0|NHn8UPwVXRdc7k8j^zk`;a9##$cBXwv)*+Q**hj_`JVPh_DbthvUH{sYzc1}8D zV-Q|9XU-AScP8w*>1@`>?0P;nn1S-=p1mgW;{BdADK-xUtB@6+zC_T zybC=Q&?u+u-%CI|z|-brr(K2hG%cnKOquoogY1i8oXoSgA`^_pX~;h9H?S|rgwFXaVzt0lE)1*Rb2)bNPF~X=L=taHoqv)zVlW zMUCvlonID;QRf~G9V~*fe9`ZvXAJB20?c%4Vl|ir%8iKDc-{z-Br$_ z4~n_FMRNz$+fbhHzOjCIh46gTUSP94=Dz&7`~KndR4<7SIgbZXTN^fxbY#~V{S^$N z`Z(I$nsb-`FD81AZ0cWdPO?+pC6#jRQlpM)#=fc|EM0M14(*rsG_S=y~A$GV_4Wt7sH#b&{Hs}MR=*&2VV9sLqz{q!`{{L~}Hn|9GG!4l{fM{1r^hcSovcs4ufZ2IdrSeDa!R#(FEVZjccY-zA2@wEf?QO<_&r%+lPNdeP{nYneRV zn3*j*fXOP+O4~4^ zwWl?DwLJ{(h`8%sJ6$oYJ+(chJtf3|H4$D<+`p$a-b45AX^rvFn*v7jMwctTkHPFX<)bS zkMHQy>(=3y{Xk@O#>X_$c4s_rd#tXHWx8A%W0&(QU~aw=XD4i!tA^I_496$pY}tAV zWg+>5{cNgXhi=Csh#*6EsM<QKtZ+oQQB#ncqd2MFoEU&nw#W7qQFfoC) zJZfW!$P&I4xqgc^GpV|I?T(aS4%*c)=;N>!T?1o{3u+pV)oeiN*;KltZbx$&<-?&5 zfR&Ms(Sl8zwdxT47!5r`MzC!m#(3HqyM@Zb2o^B!L?YvFjX2j01a55O5s~TmQrzBg z1enPbO@fEkw{N<=V!7RdRnKNF&O@Ffueib9rC}!|?Z_5hbRQA#=`bpR_w5*pxN*Lt z7w^!trg*NYm};oR7uPsknA1z!_uIKXH}VhYh~l|LPPz`^uZE&7qvsXjyrQ3+H%2<| z3Hvh9Y>u9li!Hj=G3mNPq~9n0uixp8YU!7qx9=F=m|!e&9ubqE4>8a06{oqSwbR0t|vIXFtg3;V_UE|-xv~uWF0%;d5*~9>4 zC9{9Uo6?UB5GKefA%&Lm8d6h3D>Qf9if9IV@u{n)c3AJGGIUBMNNi-Ys0>ufcsvIq zRJ)^3(sK1FX$3{~@H4*-7~Cv>ujuSBH*TFbt()SEGJiYznLThse8QgF&y*a%CtbO_ zg6bKFS=`~@_90Em=v>tC<6QPC_P~(w|CJOIAb)`;Z^gulx~C3s$U868bp zBqUZ#>Q@p*@Du$13LL|f<%|DTIYuQ}umrYt9v|D7GyHgKY=afKe@hT`x)gb6@Q#N) z3I6|lhZ%l`JqC6rv{f*o{sE)cG5j|*MI!&a9^2F_7IdtdrwI099MJc7lt2&du`%$y z_lm9#^1n}H3MBtKMXfjYpMPUmaG^E#x;hMx<|YQ70G6Y%0G8zJFU9iuQJybR`?2-I z>POTk)yLI;z<>5HuvOugXgiQg<7jkz9nqBPqt!QAGtXbY(^4h`^vyAiiN^SV7H>1# zAJ?4J7-emPB4UHmqo^mu=S)7id8ju&7~d4r%oqh|>tH-?l$-UWHa>iPdpHglS{ZQtayq*~<>7AMLDM|UJ3{y& zTAR0H4yLAEh&evx9D2R^Ya3vRP?rtu@eNjMnkx^@KllRa{ccfnCG zif!Sbd0`ahf??j$XcUCgw%fiTS|d?hg4RZIc)^(Q#4wi!YlIl=b6x*aa6-ZYO(W(D zXfRaxZLm6i?T^PA@>XQ>z#)tnYbuUOb|%IO-USw}uQw<{xmxyaRrb-=eE7@14?h81 z&SuK>3sZKsQ%^1#o@^a_w=Af7_9^>e_C~+EX+)-qwW!CO-8NZxoc)*wMG$!w<6Qp=_p$B5YCBwy(9VEqOtr|Wc)R< zh8iYkOvM<syy31%k0@E2}>51 zSpp;(mPv*^T84xiKu`i$glVWMjI5Y5o*gMV2wzj+E%Of z>kLcH3gZeUw4N}5IU$hz_j3l+_W!Q`y8eqR%$YN1dCz;^<$0gye(pOKXRE93cATxG zaREF`S1D@mid9#GdaRiwpnu0st~BoS;E zbdJJ(&{?b0oLhU3qGs*fgok!K^qcITBj23~?iSWN6txXY_-ej}?VijPNG4czOk8xJ zRmF6F?8-y_2Vbl3^oNE1h=SQ4U6iFyV`!5L82~QWYEegp@xn!^?6og|oP z&@N@^%tX=C@ov*$cwhyvQx9^HpM>?lCou;O!DBED+$QkffkBaxbwCEfcMlkaENHa@ z>ALu<@_T(IWMWaa5{{@E3tVez`x}?&I>a->gP)Mj90;2R3W8(je6oWl9+fJ_{OOiY zD;;t+@~7oAUa4-`exlb-Yn{311>XRx#z58jjERivLZ) z!7_eM&WCn=RT-4Cz`wf9(Lxz;rrR7XiQ=bi4$&7en35#Not0KOd8wWH0FqIA^mc!yFLR?Va>KWrBUyQB86-BY?d6dru5 z)Z1F=Eg_G4TyZTN&5XGohu#Y{hGSW>b@m$b%WgS zjq-!)9+b>ScxnOuT{G#+dVRdj>C#$8gfsn26(U^T{cBo(oaR1 z?*Z2aWqT%8VRcqSb7aK}HPStkqiRZP6Ma`gldiKshZWpvhR0l6$9HY#p%voT3jYty z5rs~iwVV-G{V{Qmwr<_LwqKa*GTfg_vuqhSb~f+b8SRd)dsjN0J;s;ns{`U>BsiF& z>!@Xo6r%T!tfTeC3~ucH=sJrqpc%KHd<*$#0SB^}tKcl2SraH+ zIjj!PU0mvAM&}eU;=}Jp^si397jQ5)K0xc=D0%&Bw6hb_lvhGGuBFAK14G4_`onh( z9FZQj536HF{|x8a-!JvP;;6y8{h0J(5t}nvYqKl5*E6Z^E8(nL8r=ELeQ|YrD|EJw z<+c{b2H1&ohtyiS`lq+AuEW?6BVV1~9`%u@`b|v)CRddA%`@tRL!N0>jYrs6Y4VgsSq`B5RwLZ=t zQ^!ux22$&ykgw5J7UM4UdYvDJ?6#rqn7V)XM%HWx$KBAnH+?nIIONwG>Mr>rwXxu8 zZ=%gkIof7daRob?@I1w?;rnX8f_fIzQ-lNFPrN4wb31z)9lqPjRdo!Qq+qYyZ4T8s8b zHfvN(ntLz$nFW1pYfn!wFBY$TgQ+GNnFyYm5#ODF?bg@(ca0}JIxS{nQA)r-w%8_wW9k` z|38PHLTk?J)M^hQzoOI=S5xi8yL?2`#c(?RnN7K9kB1~XSZu}_67z5j;`?VejjfHs zw*7||s12lfGJT7O@l*J&{c1RTf{H1p8lX|Qq1gA~`a5m+!!?YVUn{>oIa7`-9o?ct*wgBwYSs@Mf$?$+Kaf;fJ7WKp@QxeCx~WO724mG|m#U`JGvNrW zH7yQS9?Ml#ELP{s%UP^<9xfjOWo>#VsKKI!U}_!e?LeeQjl}k}q7%9Ht8cuAbsdaHa^!r>Y@gJ&fIASs80~-I(4h+M^KdCnFz7hb)rK{1A((Ir<)toj;#}tI(Mv zCn%cLP}PRbZH^5ZCg}Wcf?Xii64|2&5_W*$^y#F&%UGts=6_m|(c?q15`pSy)9a`m6TqT6LG5$9j;DwJnj%*4ljj%%Ix8Ig)qlf^@{0 z_W%4n*&Xfq#ODUKVzQ5VPaO1Nv_Y>!9ULitU*_O~*nic#WL%wBw;?aNE;4^6V;n0r zaH!!t(e-S~{sfhw4hoWD`PvjW-o15;G6gRJ5<&hI2V! z(p3R9N-`vqYhE&^%Fdi)jmVFUe{IX1QEsGvp^P!X7*bd0$XN+Az zpuT<7HMDMmJQqa1*SiMQscJT?tI3TCyoR2bSl5KJX!N=j9swLPBkp(2NJ`wVs>#Oo zZr9+tQ8g4HQ*$-Q|2yL-t)A=4ZR$r>(-^4HVn5&J7`(sKU5fSNO8-vh66HhZca~`C zPUJ2Ld|FA0>T3Q(?jp?YWF3)h^kz5NMjuFB&efhIx&JP6oK7a|NC`&5JJwO&4|YZd z)G$kHF~&=S>T;|(l_Tn04K?5cnvpb+lp`eLPUD(Oy|4w$-kt1p^5P`gQC7pUS#4$6 zzLEHS;;G?vLr@FJ!5Fj#)?ZpZBsi*WaP8FLS3(=b(yF*0`p})4RRpL;XoffjF7wFK zZSHyINFJi~^@48qaNsAXu2z)un8TRSH0P6Lr>ZSMAzK8P&UA zzSGv^`HJG{nYBibqi_q533|arbJp#-CStJwMS9fa9eHEt&8VjMnmLW1gEw%Oo^*qwl5;%j3)caHg{og!lgUiiv& z;Cag09$xosqg?Mb9_RcX*FysfebnsPb_>nZCS@p6vH3fX1 zvfpvdZ27&s()xf^-Q`kmKpx}<*c;QVLxOvHG4EUSvZwODkKguR$45M_df7u6;S$Ar zzkTghtW9kAKW!STPPSS>4a^xK8iwf9Sk3Cp3WeH|>kD$oAh?m!}No&&aEN`$4AaqsON zZ?yv(ySnzl+s6hacH;c}F6dNP{IDV&jX#t_)k;X8kw6z?1O>!@Xe6~2XZojVPSGRpHw=r%MpRXDOJWiDW&Y{!H*c|^G zB~Lk!!!{-sT($+-M!~bH=r)S=U*X@~`dDI034J4OpY8a5={J>1QLUUj=|O2!!C>En zGH${kFqt4)2`j_%_$VLwQX+noB6urUK(pSRHYDt@L#6MDlPT3jL3F3Bw|8 zM>*x+`olecgx_O<%26p~IYtV*;WtJWqeX#|rUcekq?u`rS%@{|kTqMACQ4lJ-HO(V zUsP;Ks%|)(3l+|m*zSR!{iQ2b2~}-Zt5cuSyqtU=gZ#v;w1n3KLB16Hr^JRzqvB-S zGRZ9KQu2NeY-x&a5uRc?;^eo&+zrMsA-KOc8EjTNOQJ^oO-i@M+{WB~AByk3yD4%k z@giL5Wev%}5aDl)0reH+us@x}1XI9;9L+FL3W{hOaC`Z^{bB13V$)oNvt|Nm89`K# zA4kf|dk!j4O~$##Ih~=}Ytw^$GbW~Cy*F_tGdgun7IcvwHUZC<-5J_; zjTr-#q%BcU_MFS6!!L360{jtRUP{1qesztVg4k@fx=W+2&Hq;iJ2`ElVtfZ(DJyCY ztqaLpN|cUwXl(Ac8#oH9>!-G{@nNjb~mp^$aAPOmBK%ks9UJL zKr3FxnIAGd5uBX;pkxBh{+IqeQfCnlT+{f*bYuk0L#|Gi&=qEeH7DJ%rna8ht3e3*mL!kE$DFZo<*HZ1ZH!bKebRt37C z5&XqK_z^tC^#;Wh&G;*bV?^>ChKcX=0q>pO5l|i#Pv$wo$N#Z}P-#q>Nnj_kX7U<; z4J6>q0nONJi1^dUP~cGGX;@QNXh~21$${|Kr~W&4Vxf4lO@&fX=0pVFat6NLJ9pe9 z-|>62_nYArP)wu@ic(~U5-MKfk6k+1HxPags(JqkZ;-L^ceu0jfHGSs@dv7V!A1xa zMg%*@wNg7s5AIpFcwGQ2F$y#CD>Mr_Ymnunj?=G8Zq~pvScsN!$Y(0!GUEda!A7YI z)NjPPnX3Y)omY!D%eOXE<;Gy8Wkjj^p^o>{wiW3q#if{|48S4kDPx0_OjTWT5OM#j z73d~d9*5u`21WoQP^!{Y8o{j|l9s@`i}DFepR7z;`j`=|>3sh`5s!#!vLV~0)e&t- z9L~AN&zk^Tq(*K){ljL+O6vihDgAEXG?y~U^IJ;x z<#GY=X%%bz@Lz&!mV=iPM_RkXFAb=Jq)4oj{f~Lb0WNIwH?bxMyqf>&_FF9L=Hv#mb+M<>*O+WTk{Ykt-WH86I%JF_E(?-G5&IWFxosrM`r$EGhC-$# zu%65s9_^MC|<1jYpG;LRN6Ni3My_X*Loy30sO=T9AkXn z)EWBjD&=wK7HBA6Tlub_lt0x1yvo3zMxsEu`7!>j(krgWy*Q)Ylmlgu2cVb28g*js zg>=j~H_OSpJ_4hdLO@$~4HjzP-()7({ETCQmam{qa`0Qmq-puxUhk($T)KsPZ1oO>*fvUPu*( z%{g^+xJ!Rp#>dOEDKM#cd*!Mzt(OvyYfNZWMu*TDdgiJTHKE9I2$#cWz(_j>_==T? zj6c&l?4<1PpXrAelo_R#Eny2V-$(VxJ6`ee4S2^UBRgen-wc@*Hmwk{o26>;y*v zVwPC{I|AcqBWp@r&GhC>Zza0dO#`A1TJfy9xTR8GzHvl5x#GVFEgW-Iqt_?;uq%KP==b-kKA~^*Lc1e zx{Yq=k&vbi<#>$2s6lzK? z&+P@{Nl7_tQw3Jo&ord?PF}VGU$yI$6`6iG(}pX|ie3tR5*)|M9AX3D%~bhKYfMc8 zaxEg~=afFuXXQ9bC6J5Cx0>aANSa#;#48tDg>QpvDYlv&;fH0TmLd|`;cBM(8MDms zfW#v%5M9N4&PdI$s~GVkml^0U=IVzo@@~D&mF*=9VXkZ=oxZUL=t0JkN|My_@ew#l6< z|LKN+D}Qe-9L7UG`Fn$+V~%VoeAjnZ@JGZvR#-A4J|k|rL063+<}El=#F;G46b)J# zx%lJ#=w3X=Zn_h-tQT)2;`pmLJ_pBNHAJ^i4byKoF{h;i)9FGvnS$xC;%KLYSY!nmp3eQUy8yQ1H!Qjyrva1Jx zs^G!cq5xw{6_C=gb&3|g9+tA{a`=Dx&SA|KUpohJ%jg4Y@$Wa3!n@t`;+U(Cm0!G^ zB+h3RG7mBRL-~RvqeT$+0U(9!m66fmJ82Jh# zS<`=9DU%)dAK&RNS!^ELg0Y|G@!`mmd=-eVfpB|Y!WXtOHQFy%{&mv9^;3nlrC9=J z>Imk@d&91;lQxt^c>NBp>BL(Y1BRGygS;2#gt}b{i#_yj%SokjU1-nRf9V z7pw%l;j1|Qj@I;v|F}#24|h3u`!02^4CoHfT{N;H0wdPqJ|BXill*vjjwQH{+ts&j zl!39mw+@IwGgC$R&kJvD44T*PzQlXYYo5JbJ2%7cNUQP0f3`i3{o8=PFTuBF+jE!p z^rl-kU>{?7${%HUvV9xYqGY+>+q)D>D}T&>62DdAbJ6Y6zG8h8=XBVXV?TOJ=KakJ zMC;7m_JZ@#y87=-F&Zx+mV|e^O3=s|MZB%`#N{{Rw_4)r?XJS;P z@n4F}KfjgdpWhnvC)o_jWo82g6Z$4%DF>ym&84&Hor>>L-~HFS(|q$Bu-45=f1cyx zC3tON~??j`!HIpRfFpILbB|M_A4l`5XRNu$HJ zfz2nU97kLM+SAnU2Mff|q=Mh`a`;@YdYm>u8omSJGwA1SZ(q09n2 zFMjX2LB9h{A`aYS49H`~cp^fb@aZ+%WwiVdLfT9y4MaIv=nz3?lw+#3P*_(U=BoY1 zT;T&-oanenS@_HSN-u9pDSf1Luk#2A%NmZ*g-nEv5B^cqO_JP(QqYEwghuP5t#@L-G{&M%UPta7YHp|y>m>vTa!~QS zOxk_Htw4edGRBD~F3<{3KwiAY^^~}QuRwoM0?(u}fnnu91u|ADV70)$U@nK*-V87h zL$8zhAnS7YhICT08Wvn-c}`?eN9ycE#CsJyqJGKsuzTyJgsQJ9)uLK$hMhe!54!T! zOXX2b7Cbu-+v}yvD&|!va2N%yx)m7_7Vz1Bd4nNcapcEF@=UD9i6KFUH%~3EK>VaF z8ms&zXmQk5GLXA?0qZwv4JqQ9Hd0_@F&jNEulGCQVX(?p8jGmiGRK>^QUz4nV!I?6lfaqhq&pUZ2&JF^6#g-BX%5+zcLS)Y@tsmz|(Y zh-r11kac|?bADkmW84CSvpKi{+LX|32U>|g3^o!l%j*yPlavnRnoO&|94?lqU+{-- zgjZl|p^$cX8Tsb>ntexelLMNrN|f*jEZ3<Ug$72#Rk337HH74EN9J$tIt-jGgupWHO{)Q-kI=vU^G47c6vT~GV0?G1Cv86 zGtBr2ezNG#!z(s#C7#V{4$}MVu0YM5)(FTdpGsLoI^@1^of@zXDYTQN#AQ&n<#1tbAW>3|O_Wr3rQ{8k6n7=& zZFN58PXSIKrKk}97Zwec_^}CU?wkkTJVoC+f8!f0siKK((U7k0IDkxTuIT|8WI9uJG`MpZz2zRC+S<6s0G(I$QAstwoeEDlSNTvGS+}+HnIr&A-7me`!v5c7vi)J(_4==*}cJ`M1i)@A6 zbTQ*={N$;OC=gE*N}Ti1;y1Uxbjgd>wZ4q7-f?Hp4%sPEyx!Rq>CG)Zb(fZn^yk3= zj+C{ZiigT|k;Cb{0xgw0h~Ya57>&+Ioae(}Q(2&!Wu~5jie9dw>hZH5bhDfn5xGd| zlwOf&QvAr=;&Lea$x&A8*PG^zh`|!d3l}?n1OWrXCBV23cQ=PfFPjxQJZ7tUX zBflh7;1}k+9^`mo96u`Z8ce9jT#zx7=w1pWkY9wjx5-y5jyIo7GerDYd!r$5Kh+R4?*yanAu~~m>2$ZfROLOy}Q^86D ze94dUNBcsdT10IRLY=F&gw3j5kp-+KvwtA$7=RZPE6ITd4Rq}y_fHXz43Ld@TIM6w z1&9@&MRubZ8WkA_Y8=a*{h>ei$a#L-G16ywoy{d=#eU#q%%nd9p1masTahJp)(u1j z6|DI}x;ZYBMVH(@#|j)x8?{q8C->-q3*$ zT6^wD8KI*`fh!z}hWmj>X*m=$I5^lFxzJ>&mh!-u3eIugT1OkNIIrl^A#2S5ZssFp zku&Jr?4W7=MZx=_m4J>Mt(HeAjx9og=Rxnm>V!TTtcEek6L^MXsKP{=mGFD zV8u@OTs1O0h+_-mq`aPw2~g?o+y@Z|aVwrFf~s7I%wWdYY`PqJDID>(owr8$K9)W^ zdP3XQut(A!P4q28F0xlpiT~4Y@GZgiR`}5t%?`CVL!IiF-MMopm4;SY(1~uZmp*0=It}0(mi;Kj3$FLCnQlK)##S?O{iTYw zAIev}gS8cJiTJ}Jp34H0%Xv98IUIDB`55Cyl-!DK+S+Kn9LkipB`fVuyZuCzhoTAO zJ!b zxfIUn`*C&Tu0$`NIS#R7nyJ;RRLyyEu1O)H)P;|mg8QH_l`W}8ri#zC8K5;$2!v{3 z@et&v=z#|E59ph08{2@fDUO^aGY6|9nf}kRhD}8$i(n0vf3=D++{tnkiDP0mze;~R z72`@GYH%RDalpK)&0)dYVU6Th9SE<5N09iBKCfimd5F0)4=RP7K=I9_;QJtt-@B zD$RRKhx+-9@qRW#8_4!~RsvIoY`eL5Gf4xi*#d?lZQx*KtR=3c8SyP+MeUZs*oW9T z>dsRfpFS@q4C60jJXQl zk_mot1$0+6c8~L8Nnr;bjC+5fXL$)MEz)TDj3teh&)Dx)X;wm^v6!u8GvfUVo#~E3 zSTDnoaY$E16tkb=i3~Ur<`ObAXci(&N%9(D0erG<-Vy8I@ir8~BTjBNVdz!W-+|*n zF%?V$$QD3(G_MJPVCDS7JIsXY2eOvfkrk$Yg?55h@=;`0{MB_HEEAV2-$xWf-@_C{ zcgIE#I&~bn3mh`=__((!mHznx+B`BzQXc&nrBi=R+X}tY@cp;=8>wnsGIhHhC*GmRM54d+4(+o(*&} z(eu05XyT+|q7}%l8V3F<%xTdH;MZsHY)5vGrX7u;Bm7amotjSjSddFw_%5c z-l;yr$C##~w@kjtm>RY`kgpF64t}|V-nPsdWD0E|b*HZI=$rTFa{_UiI$t=-lr;HvtUC;4k2FIy6b}5-M$;PjH9j){`@2XR zV5&7~Ts2>xyae>frc$IVyh>(HQiIW>0Vv+vWjvc7Wy&p zOOz0D_h7ey0e_?+f;5U2?)r5UGP^9k>0bE#bPAi+%?H(<1)^T3t!9krruh2Hq1>KS zun(nUG{3v&yz~$})baJoYY(nYH(d(vlcKya-Lsj@P)Oy$blN zSoee@G1a7UsfMQj7K%sF{Q(~<#$4DYBsImG>LrKaAHfM;@GcsYOAAXgOA;I$;yQbJ zlZ?71BRo7tQm9MN*|QOcAbppVid-nBq`3A$X22TD|kPlLhZ zn&2IGSOw(Vi_8RAl^a!5QmTom;=>o|87Y6W+{Nsvk&+BwIk+mmiiP(k9V)NO;lKI1 ze}Y$)GeNEq#u|03WgDB$!x}RRV-c^kIJ_mH6>9HdUrdd*R%QA&{MLX07#dCOm*5q<+D4yqkPA4f zB@>(!pMf=HfdN`Di=onLP5{@d(*KE~@YEWI{02;$jpTXK)u_7X%aPBc$TZ7>MPayE z>e081o0ij(+T6H5}R&B*X4MpLyZ*g0B>my_Q!da3H*M= zKFaYLCR)M&NqY-n^QMX?Ix>ZoR zRf@^|l(nveO1#3Ps-G)-i=16Tv?yED^|W$Tpx&8*`^Kw0v3_N9^!Rvx%y_$a#$^f? zK=J2Im+I_7eE-DtJMy1TiVK4ObJS@$6Mj$&lc{WrhxMt1UW6Z7@`HVrbvZ@8pwc_S zMtSLX7aa*EBI?1lgRh=H6jcA3AFuTPrki8$%N4p<75tl{napWFT;q4Q)Lug5SUZAE zbd9lrO!yC95LuN$Pyz2e7SFFlUjh3SuXIyHCPPq)PYx)n-j#jxW5t-(H9;`22ez)W z_+r3&9EB~i?+&js2xqXG&JeJ=HjNd}x2nCo#$%|bT8H^ZL2(L&i@oJpZUQfxMt*zV{R#{eugzxWc1_w7&mQ`f|lptEv#m%xoVWE zJDD3LZfvmxSFR)efDE+wrOj!$MxRf4ZAmFuu8rS?wuuoYo~cDc@r&CRZDbHZBu<90 z;^kJ$x?=f$TCq&#s%1@D@kBdeB9(Z0WlhA3E|1q+;YlyituX`paGQ@*b0gR@I zkreLIiS@TQ)RkQ<#C0s#lW@5f3yPE73BBdq~DHs5S;vc?QijhJ|;$?QlF z2S!5Y%0%9s8HWFTUm05{e&5Op#QcBq@>IJ@eEg3h%Ch}v4D1yZ_RnFXMD`~6aQU|~ z(Q?lrZ}kAit)nNs_cFr++>L9gtDLjpavrC$|k~e49rxN z0H27}&jjG6kOdYrL%SeaT!BbN`U%U9RJxvt5)-7&C&bTeL%!bb%>#|*Uayv#KhEl4SCfp-_4qazb z2^=Bzv?c-%^N`Kt*j?gr>`1BIv25qOJfQcXdchh;h*w&t!Vi~=BbT=-CL6|ojMj|j zhSzzHANMuteAVlAfO~7C_=h$VasEu)U2;ZBXYU(fO~ESvI^Q>h@kKu4D{{FO*0@c& zIfyZSAf?A!eAOl3{_N)a;>~&RZWpk6pCIP9>znpq>{{j{l?YEeWenY%i0mIJUCxb9 zH|~`d!nX^2nQ^#yU-MpAeTlv!PqMZnk1?aDE*@UG%h$MWgU_~ZC0c$KW(>B?etYYB zEA62^Fs)57$uREQz#T;h@`b?uMay4cRSUIh2ciIutVAEFnXL%)IGC}I1Z-H5q^?7@ z+RrKHWkHV}j8Vh$K9}`M6mqWbJ>bey!G9y*Q-RN1e>2`eqm*6MEWZ=RGR;2+al2}M`-ms$2>1*5xN|_3G2rB6@eMrc$P4Ip zj1UL6xPX&ih&ME(Rohdv)Q&A}YtuE?BjD{c+7TZafwj0|qG9Y|JS%z4BliB=*Vs)_ zZvH73JQgv6u3A;{glR17pq;P8x-W&^4e#*kYOHQ}sHi0cQyZ%yWUswmFa=>OQ)Z$I`o85+3==iB; zcg3nVu+i>4=)0uLNuFTdGV+G2j}IJl)F_$mm@WTA&8NyWZx_v5Y;sRK;NKY&x184O?(TQQ_!K?!kGVpXvANT-}XF?7~|VfqfNJ8Rcz4)cX;?r`_+N+ zDDUgt3LOs*pE4L#v%|xHH~;l+osJpv9(XAZNwZ4deDv>95Ga$c5ByzfuCj-|DJR8l z&gRKKef45FG{sGu@LZYUgY%{do7@NIrJ0^{KL(3V8DQrPJN?+6x20pNFM)4EsNGt0QF??Sa#KS(XewRdrhwn_`D=_Tom zVc}cL4$nTK6+e>CUI`y~^eDW=EKjaoe6*Zu-770gA}i8I2qMhZf2TBlF7XZMsxx-dM>g&skmTXGEI!cbgM<@9bnr1?gZF$kMO;AIH!UP{Eb`ZZ}aZ##hK&CbC zr|$}UkMVj|GUk|IOwFH?c0;*aqf(ux`|9gwK16tjuU)Loo%=odG4=8~b*A4@JG1eg zGONI4)0>(u3SjwEWB#R@nGWl=JA4TGK*LV|-Z#G(gO3e%;H0 zxvDvfVuaAbG(B7Yw$z$6_V?e0KgUd*Av|-~4Bv37`2Iyxa0D_j3Ssk zh6~1zf$GGVs9!^)ao>(#^KQF*j?RlatY-Id;2^vxDdB_65OkigM^Z(uIR;}NM#7i5 zc?>cx7E1=EboSKmcxEclaEeL05m}EGUUg0d^84QdtWcCpHp%7CE5}K7>c=DE(qDDz z{HMXp7YB8MmY*EC{WxI{N}&Q20As9D&^76tXB^s1XB>Y6ibA2}&&_mbeeATEMX$jJ zZA9ySZF&4~6BI-xNhMgD2p7$oI>W!ZX$4CwFvqk42HI6IN$0F{R`<>_q(YaV;%T4M zUZCjXCZfdFw-qkL7XFd^c65|44(Mg6f(;IY-yC4l_e-Bz2X&BLN*3hh(4OnZq?^`P zbD6VIO^2kL1;?a*;ESi8IwbWMu;z)dTxTGXM@Qbe3N?o;Gmh#9mi(r5R4{UER6r?P z&6mOd&!mqEuy?-=Ri19#HNApxPkO0TD{Oa86i%sAsoa& zI0Xz9oM14MJ*sH^=@FZ2rk;#)=+-4WE7#5R?S>~a;(g%GCBq6_d`eb+04h=OtLKlN zaJq!QCv{eURWWnEKMOHTnsKAL2PWSIp2T$2$l;!?PEKf1N1e+PS$?aWRiimo4x560 z?d};K+~A1vu{j%x`VfEZE26&TzRWXbCs*}0a9?&Baor=t11+rAE+h-w;bgJ2Pv10{ z{6$*IZj4&Ic-CUXk>}gp|c0Vz5R0Z=4Ha6E0OD`cr04@ z1L0ZZJ0arkVsI~o{!(&M(7dS)n)hqvGOaDz=>-1<%Dr znWy)ITdh+ss%u+*b=os3N ztQ!OmHCwMYy0Cf}9ZCyYHnrkC+-V!dD^pqJIkw)042jF3e})DH4>~iTrO5IJms8}< zijg1{*-@O)ggNN@a2vL1q#hw|Yqkrvw=TnOBxKH6=mJh^vN_^~B|xfnhJSHGg>lYS zdpY#mP$Y8@_rTG=yh^K~@38uyw^<{IUesok^dW~$@#nFcO;doDxdFI?pWd6otx5}0#2JOp%^R^-hRI?R6(A3Vn*jM zMLiSeQeJdL^ceOob)RBrIoe>ApqY{ipSKZpd*BYeSNoaqno}z5qkcL(q=Jn-69}t;@CO6rKge-3=6(}k?~0zWd{{U@Op|Mm>zoR~ zy)H&bY)XV~?qgUzp}oUCN}{p%85LAzfXI@4?+Uir$y%G2vxeuP?E1WPnejRqLs!xp z($~yZ=@WP)74dAw$iSJ~tvUr;J&b)9(_^jaD5imR;aY)RGg$4HqJx7ojYYfmV^%O6%L<;x9X>H;gbe_72lmCN=gN4D`Rr zurrCVD6u|&Iy;hs`gHb2WJ=}BoVQA$5~z0SB@x|4P3bRvC)P#za@IvP-3NZn!{vN~$p+W1k_DYhp_CJi zyaKHlr`7aqo`WZSV+eZLC8+tPgWYcsDtI8Q$DGI?PRCgCv4r<9Sm%A&nNkr>-YlUpivEp^F-dKq>OtXb;ha}f@$GY`dN zvhC2J3dWft@BY*+!wGOxT3G{Y`vjlJ8w3LCBmAEX4cj~UX)TVgDiv9jv3m9=Onm7W z8UGz#cJqz~1p2cfUiPU{E|?@+Y)o36a}=y2cJy!TA~FcMK2l@99BL3XzDariYG5ZS z#*%)LbdoOtr>D__sKiZcWA7QJrG)EZ68x0~zUs! z4m=$5@`;D?CUX3nVc%Ex2K1(e-MPBx)Neu4Ng5!*lXv+Ntn z+_P%ziYcyHtzh2t<_FsH&2i#XJq>{%MUnKWYO7g^p!Qe?r1_ppKZc$eTq6s;0@$L_M8@ST_T*pk(W=SDZt2t7kQ-4cVbFdcCn@}>fj+Elnp zD-PV?f`z+gh~KqMSd%UcY0`^hTX~EoqZ8uAzh4}`hB3mQW!ff{CV(v=Veyg;zM6H8 zrlj>tVC|H0EO0-iTtL)qr~1` z19CB+28w<)Jh{Wfrx3;H4sQl7Gfw;ljD=9a4fg<%nt}0FA?ZLW58)T^My)LBV4n%Sq^Ds0 za_3duPbo5jSgQlY?2u^xR*c}Zf2(3R?YA~wb3MiR34x~y?34CeTjgK(D`LTCr1{CJ zoMNj(f$Ud{zqtr~K-iAM#NuAdlMJ})&%-md*w+NtcS1@Ff!mFRmeLKG>oAR9r@x73D6Vp^eLeNi?%! z9C#5v$7hi5v;tS+aiypxF7r7*llcTzbewUi_$aQlKJXZhXSMmakAE0;VWCxn+@pgy zONFz{O)JVY)6X<;nMEzdWnk_Sv^ZC2DTfug3?&}IJak69jQS-s0gi$n;k8@T7fj;n zW@Z8-e(s_yd(>;STKsEAI%@gE`~q2STGTT9_}qCEP8{46;+|a=Y5ZOURKGr*$MXD!QKM^JdjLxSD%* z<;iO~n!_3*a~L8+Kh9eQ$-*0y zDgO8KC$(}Jw)WM-Fe4fdN@w)ihFJEkXpjVQA@! z!WCo-h8I*~edI_`0x3n>;5y&yxx8OtGgzd+{4bC{f;M@x6nG&-iA3ukq*lWacrREt zp_8+H6?4;t81cmp#`vbxs^3tevp`kUykP~|f@-YtK4bj8@51W7kEGA41_#Icn!t8W zZDqT3(#m?Op(V{)h*vopZ1waTSntb;(?j$V1e4&8u%c!gh!y3w_ke4klRE( z<jo-p~SjN4%YY*;~OotKc3 zjkxc}*ggZBgT;!T;=Gfg1vws8!ex@tnvoVN2D-EMnFWalqsreY44ruj>Ad@cYy6DE>L331*YKua*E3R zl6Z9QQDAb#74q35#oUg6eL?Sq1p>@mlrF3#YnMDfv)9A(qvmwPwOeY!m>eVSx-ftd zI#6DUaj~_>-s37j6secKo$ZNDm*aCY8ROhemNf_l?b?dHMo1&37$+|J)SvhwW>gxT; z&_P^s#Fx6x>x=g;Q4^CK$H%+ly|wZ-i*56h@g8%}mbGTYniBKy+Y!dC01}?C3Q4k6lhgJNlxx~ly7Q*nF$N24&yDcQV)ix7 z#Txcf_{fcN#Fh!W&YA4!8f2VC{B+efdZqhu59s}mLwltQ;pcsonPaB_%*k6iTtY)HAeML zS?Cn5MY){cb-!;P{8o%$_=||M~ z-}T6#Q##`yBNseiWP<7N*$xu_2YKpGPgK`W!<_Cd8zkPiWo=@rwB}*K2f)c-xVM5q z9MG^=ik{@jog~-r!KO94@Q%^LaBud<`Pd-7*iPr_C|d$3E=AQ)x%RBq)W*mYCW(Wk z%TT^bgVI7WvP9vlT|77t^AlT`j*HmB1~8WSC$c#-y3-c=QBTb8B3skYqjpFmXxg}ml-unA09xeZ%k0Mp^(3nwmYdPEc z0_6G?_}FxeKY@6oQS9qj5hNr-SKGs|z0Bh8+X{m;mU$Ga^XB#DrU-&7Uwj@&GFrP4 z5+NNJK=b-ktUZmw&%`fV&FkG*?L1>P$#d5T@h@$rpqFMtBXNux2n}Rr#NdsgG^%Fh z_*yZ3deuCv*%9I+t&w9H(+6FAENg_X4`<|c#qvh@?dU1U1}hL3wvjiBN~qwU$CgpN z(4s_1HCa?&r{13V?cg8A(8{AKcY;@yL747p0r)IJiIrkBtzyJ4T_+q#$ojtE+BLV< zZtre&-6OZkq2gW0qA&m*G#`D82@U~{pTi8!LJ7|Z{KoUGgh`zeu)@~gF3ok_E6!?J zi`DZA1C^*+wYG>x76reyXf0Ubfq_`OwkQhqJFmmM9#7!TMth!z>-_#A-UPNsiVw94 z=+kA2C+8lMQj9hsU!2)i9jtduga6dK#wPTIJ`BAC445*`h!yK+)*6Mq`#slwX)f3X zcniv4V6HY`&Erp_d6LVXd3^~KKuoUA(C1fa4Pq2yI*#?;Z$qW8oEJ!D<3hW^U|a2IPuvF zrj6%;=`so_z#7jGZ?&*Ntr*{%?wkyq<^l9F#@HXuld~X9VnLgEBeX2g)8u~U1}5vU z#%vO|wGaEk49`3REyG5K*{6qXO4g03P4&BMwCQwk1$}S}?_al2a0%O_JqO6!G0?UU zYqMDKBUoGuk#TZ&s}gJikNU}$`Zl}-@zRI!wlUl6$`V^HSTR0Cwr5;q(lcQ7GI96) z@Vgf_#q5BkHuoO% zg%d5RVPuu32Q4Lkkg^ZZ6&icDP)| z*f(1o)`5D|6#yUF*v}%84a6nh6}3x~_*;x{YcRs)piZC2eg$mU@DUQOET|T9fy+{1 ztbTV@y6~E zw>UQs%;Ag?u}(d_@@}Jeyp-XR#wxP9Wz+TsglC)JIG-gT^;R$u( zZ>2f;DQMC0q6P7uxroa3wnqGm#d6LS*)Qp~r9j=)PpZwOwjV2|qaLHgzjZ{8J0c&K zARkvKALjv!I9-tgMkCz@-;yI%jFr#%Jz_~ZSOKx(>2^AM0@gEx1xdwxs8ObhPhF%o zLD);6RK>9u-@)t%c15xNMn#j_3*QGYDVxAC#_VJF@%t3}RASl%G5f&e zV7i2^eY*y?`c&SvzEv`ElMtD6frD-4kll%F#tNy@S^zLa zSaoec8;0fy>VK$c=u>0 ztJeuVUf}GHWz{h1bDR;m0^l=&y|p`9{QhEuY3tJpynDmWqh1w7Q{+iTtIq8WrMtcbPw6|-AFa37op#`b^UR`- zfA)pnU@!IXHM@qGM~a1*MeO4LVeHKVqo}g>;aYl2XX_A_PQubl60#8JB!FR2n+_C9 zRD$Rj0f&Yt(*ZO=P=hks0h9nbhJ?{9qG%i^fM_}qH98nZ9d$;>x0}VuLZAdj6h_}_ zI?$Dbq`&7>2c3C;zxVsTKa#HH)~#Dr_nv$1InQ~{*sU8OMdEwyi^IrheGY6`%^8Ru zkCLosLuo*uN&2l}e=YeaH|2!K^DISH%!F0#9M-6INv`ZmGmQpguVPA~4Qeppv?KG-uvmY{=jP8kPVbb~yq>>qwsi-!Ny zmu3x_**#np^CDjpt~Y73u1;069CtGGQOjyoQK!f|9|^mgvIeYL2#had;jAO23e2+$ zA+@z#7}X}o*PL_(x6etLgEYzVJO40+b-i4T*KxKnQbCM)JQvR-v7g4`-UBoOlb8JU7WXxz$Z(;@_YvJUEj3hr9JXWlI?4P130|&}5on?*=|thgmB;bCFFX zXIR_ULffCEXje6z&@S;NcqyfSKXE@A=spEPKXeZPp+rv)nFAUY>o))EpA3?a5L#!e6*5@ z_R%{_mwxJ2P)=T&mC-iK`QSugaVS#gQZ77t50g)$!hJ*1oRsfkZ%gkwvv8ZlX2 z$67G5%d}M!JoH|s2;(3NTscc+tzu6Z;jP2W{Dh|t@4wg+mO6{BccKR`|J^oNsj06g zO1Y<1H<_lK^Ytik3rmsX{;KED=JSa8IpGQ4o90VepR=d54ck1IVV~;6iW5?QqZITG zh3g%Eop2K-eD7J^H|%uZ_()T^88KA}-APKUZ6v<_=#H6+)Eq7SDP+Lvw*WX-ZZdhA zs2}OO)sxj7i={8}TkY&AR*^Bf2Iw#~5sHq|0Ur8vMDurG4x@J&)vmQfSX4Djp{>5t z$xIpLRZnKU+~i0fzLBXGIhJUh1^r-nL@_Vj*d7YHkA}aVbi~&jrN}!Ud<<$q+jKs- z`nt9W8UVcB=YuP-{arA=&xv(AtU}Nt8cy#+&1BajyvcLeR$smIQ5&>urq9%-1vegD zXTJ^^Y>D=#Fwe<_h6{mjf|e)4d&wr1KY^W)Q3+(u`QRk*SKa}1-Hq9YWSl;SBN1?FFoI>$K4)aW(T@z^J7fM~9H%RA-jFT5 z(rLqYys@Y0*zaL2H}>N(V?2j>PKTb!o3#g7=+j5xOA6U)M5+bZK!&YfBY;V{!|?xY z{~Fa4FWoV8!w#1ZYfX_Y({mI|F!{i%9L6tgGZuP>v`3oGVPs25e1`laX+q*Nap2~( z;C&N^q*{uCbd8i!z+VJ^cIwL;=+^|c-<{5Ea3)^^uT-zijD4q*bh{kL<(59urqZQZ zU8D~dV}zp*Lyv%z+X((q+=JFAdg-r-i~2>QnB8pJ#sE4(4 zWIbixjPyroU-L)lj9^WkBdDLOUZ{9TDy87_o= z_wLzIu>LJyw^4bfT40>$`bep|BTYH-?@wrvzU>^@KsH#WMt2CK=n$=9mkXYUCP?GY z>KY0>%@6537lWq;bq$DXFtx6E17&F)c^HwXcxR?1Dh>$Ux8W;C%VB@f_~8FVn`RRd)C8T#x2u%E!#1FU^%cgH{nO?Ko}1m}kvbz@!i%YF;6% z3!NV!eU16!zk@L$?aQsMRu9&ec;9rNG@(8zyk6sKNK?mH_jh- zjBn3-p{~eRD$twQD;VFgkw?WOMQAJoKWPGw0Wmec~@}aXp(hqVs?s zEIXMoh%qo@M)Jrmr^dqqxuMVA<_P-g9mPN%N;~LV{TizkCVPBI=31bUvI+A>R^6ds zW8Z7*_sZ?IJxO&A-RZsZ%?65V@VHwN5#JFw><-U;k$7jnM9{p6qdHp*+VMv>MN{2u zD_;G^{VxD#GF!R&CHJazY`R^lb^l)0jXsgM+i~nl^?%fqk64^s&ziM)=zANnR#~&U zxR`31Z40-L$=vLv7P4S_mF5ox3)_m7nKz+hbqQEN9HYRKKy$KIX_pnX#UuL6B;Ag> zs6A9u@#^AL#l`ge#dv2+eCG9*b$GtQJ&re?R~FcwhL*X2NHj zhrSvQ>!}sE-5lS!wS>`|ZCkxMx{aBf;VZ@}&x#D};kT=6r?;E2R@a^c536J{wi8yX z#xc69cx_|b>dn<{)^&M8@oLr_4|Iz(-y+Gc&=rZw_aGm6`!(m=&k{;qLH?>;zZ>Sz z!Du8qteeT) z(Vh2-@mLp?J850_a@U>WM=s;!sE+i4R(r%LvUQRc#et`gvX1v(cZhHJBhjPcJD$J{ z8IK$ruqeULP>UYz_}O9x>$#a&BEK8R5Wj{-`Nh=S*2c}&4~sX)x5CrhrZ{3t2tlm@zOT&eLt9QOs$;Iiv-DG(rW4GErHX=^H z>XFwTStu02Ll7x(osep{Y65dUi0m&7k(LZ+o$%JTN93<CbPP_(&!_4V$QMd}Q?_)P9<=m&yk#RsIdk0oVE9?O;}1V@uRKz?bnl)~ewr zO7Qim#+)(>(f&0Ywe#z4DrFOXDcAS}STVs(H4A4Gy67p+yZ6eaCZM=%`C!(u>^cFC zuyA?n)+p=u!1q3GYnHbhOJaE-U*}xnwex$OkAZ*B`hoVY_9*{`s3`yDs0sbgUdLOr z6#)ev{(jJnkKH4^dZq`z;jajuTGvYJji-LoKZ3LV+mmk{esa7|o5ugqe?0rS;Hi)S zkxsv3RsLI<6nmT4GdagIu|?|`rn>hi`Al4YUpHb4|pxR zs8lJ?UDO}!QoZ|NCF(Lz9USUH-{eNOvwkDb;@iS=!@FA=T0Svua1~L!6i46Gc7~qr zDeu33(fPeE-Sh8Xb>#p0RnLLz>VPZ!UC#wqhY}Cw$lT2~AwiEft$bNCzSO0z|Ltk$ zJ5Iy1XnftWikX8s`y%lFGa%Lfw{IG4&2*CYA`|mE-UX}nKg+2PeHZvu@An?P|8_=w zz+gES90xni9H9%(*&F;(<{N;qU{1)#uzGnMR+qlO57(#;wO9wtGJR1-tiXCUi6p@D zy!HG>dZUGcJ9A|FkQJ*qSv^bbU%~27vou6j+5hskUxbX9L-7kMy?hCS`1xO#Fq7}~ zwt{=}SKj3cXYifg`&>-cV(&KBO11Xnj`doJ(=t;=wzCsC=;-{!OjlH9yf-@23>M(o zu*`UE%f@nCKJDHSBU}}@$X_|Pd5fU*_l+=0x%vNNtAMYK7)worf(-mz+jv!mB zYdN0$z5nCMb;D1$A)weQ;0*#|u z0sS>zwC zJkt5kz@0%2uxpGo3LJ{UC2eXH?z`O`jsM;5NL(9Hq3JyhTk7_w?8w)w^3UcGW$T~7 znk?#?bHOhMOI#8Dk=i`rV<0xp1)B#kUjei6lUwg!07l;rWDQn4&w|BAcZ{umZC8nl zul_hY4irn} zC&Ohd)h)jUDx(_t7)uScitGeqx_>3R%W(|(yYoHgDzO6e=^#VCb)5?q52krst{Fm{ zyiBI63*)KQ)fXtaszD$7F0dQ;9WAm|72sR0yuM4+^mZtAWWsp{)VfpQ z_TY)Q?*jLtMVsL@M@`6sd84MeS1r5nMl{ylMaZ=@mnp$a`X+Y|*6;L1+|YgvR;$y9 z*>1Ei8e5sWI<#8EeOaXl=(ScU1CrzpZ@4vcmDZ?~))=pcuV=lOCw*Yo6}nxU&E)OX zATDXlH*-CrF(FEwdQMfF!mp5~A99$<6cdWd8wgM&AI7&VDeE3HL}jJ!!4QCGhwnc9H@6BBY7U z>iWmGXOgehL8M>9o!|oks^mY%hCQj4|#M_NHxgBNm%Z@|| z39WnNH*Gxr-;{m1%_rNJ9BzxgV?oI`h#RS$&!eUwL_}TF5PR zmekH?()>PWiNV7bEHAB{Uv`vo#(U+xHse}VL9GMq?7gF%uq>68&1c#RO*$shbsTSg zYiZ%`G!Jt*pV2uHKRTZn*(mNGu~Hc6l~o#ng{J|WMPd(dUbmNwYhzP>Z%@9YR}cNyMh80O!tD6orxufsnbr0B9@MFB zVzMs!wBmUnbkqf9CChQe{W{fj2DzFj9*1eCwiAo_u~NOjuA6gZ9be}d>D#up@oL>h zV`glJ4v2-QQ_I>^X3qLk;Mz5nSwu{HPAc)76zJ2 zEXXu=Kc1{C1^$r6(xejdtRzeCccwh}0yKBvG1Z7C?`0mD)%uMRVfX^LfLM!I`cvSc zYcI%oaiMhHE0!YXa$pVizXEOxY|G|2#5ja9IB#4(cO^dmJ^5u-{v|cX=Q}Q`*+0rJ zPaTCXoi2!_8PLdS*7zx~@?DBsotsT4x5~l*Q1B9RFdf7HPoR67vU#j^Gx8!mV7Ue^ zMK7dC5BIP@fv08DS=h(33DHf_t*O%IFXtUaEf_;?mi6eIBY>#fo*nNDe@kgG=3wxO z63gDR@X6n@Khe`&azeH@E1u0+n4NX`!hGa-p9gEd9caHh7J7F@xVY*ivdMs+7RQ)< zTcbtQI_6DcP$oVD^^Joas2-%{k;L>*cLh*I{r^rX$vr z-pojFvVVgAe8ZttCowLH*1{Guba_`iGDGvdp;h$N?G7Fqz2lOPV=`&PxR);OJ+?GH z|MFHmPuQ9dc$ReLCsk&)TdyTg9U`e93X(d0RD7MRw7A7H@Wt(g= ziKX~R`~6>ONvx|MwO=ahPR(RqfJx$ z^fzn#@%-|Hh|EhJ;p1+UVZBIL`;qT%riaHI zziDa>#znR#GHy2fCI>j5w%Y?8ZdrXCT)XP?|DY9DvZGYllvBNeg^&e1-Z(GOu;E^3Y*d1va{tG zIb#XcW%P0 zi0lYxRfcSuEm9?qay4B^SDAztwUmUY|LEtJy~ru|ENs#@aJ@Q-dB2VP-EF>wp;m+jN` z%cckR%aiV=ZMqIu6|y-C6Eqn+Te`4%t~D>KOqEun6&+|*y}2HH%ZK;6Dw8T-GGi46 z?IIO;mvEV7JCk<4{PWRy@X^utOO{60l^v-DPw3O78dnN%#EqqP#dzh5QQut+dC#_wWuxvRuEmcbC{#RD7ZwlUV*JIzvbEgx>Fq1M)Pg2p4Up3R}vnaT4|LgqL=ZmvLnAUqkr9{Lcg7k$VUcHv3FaTj9IWPtFkrz zLU!+THgjjoyDej>7i8x7EYQZk!niX);{G0NzSS+EOx|n2_e{*MZlN!HtP3UJ6|1+C zWv;q~?37337;~!B+C@i>Ab!t4wG5Y`clw5M2GJSfZPUR8y8-3w)Xr3?t{!u$yw_kj zqJzv%me|w$LV5-R-t_qfrv0`9Jmy;oBa1xfyQ zYuS_RE!SWxOUv$n-CaFAg2OebeOBanq7`YXjWg@SLwM@CVmQP*i5@dNy@ ziQoo)3CMAk?}U;Op)dGuALU$m>pIEV99TkoVO35a{$jdUXg;lyBQ{VZ|7b*^jA@&J zH?m)mUElawwrK6^@}CM}hcj!X7q9PyPP46zBtb4#8hdSX5EYpLOZe-3w3m)OEs~r5 z3K&_zHuuUgZj0*-g$cNBh4*r-oNmx$M1RkYJle zGc5SOw739oB^x?Kij>+#K41=#Qks)2S!-#1mv(Taf9@1Do;`rjA|BhF5B#5%5#!O~$>ftBI(I0&||OX^!x1aD7NSMco+z-g)B9 z`!;xg=)NpnU72@cM`{)$HMtEPW3qG|BeUGnl8UITMc$Y!yJW9eB$~3ec+J?JS+Q2U z6D38rreh+0E8KH&bV|ib;3}>fQjO zNOK#1#SXpI&1_r9DZg76UI@hdP2iBw3m1ZO2eM%y2<7HFMOY=qW_v^?8}>;sfQ^lN zQ;et|(NOPT0^hhzz;jt8U-w@`?G*c!ui>{mhW}Vm){s6H(eP7X-Icu}k8{VAbH|i( z40N}6;itfTS8UFw#Ymj>C}%zH2;lkNghh9>x>RD-txBzp%DF~&L_L#n?8+-{CWZOE zSel9J7vlO?MH*9bU`o&pUGAsAfBOxs%G`ZL3!Xr3*7Uz)J2kjZHwnFEjd$GYacxOe~ zlu>9!wiWy$28*ic+u(ge>U~ku(%{>(BjTP(EAVC`{_NY}k|ArQNl1!>4Dx;#oYqJ8 znkRl2wDsML)?@yj4y~`Zxj5I!q|CsW8=u{G@wpZ@YjOu!lg2N>3I%pxlVzMI9eTk0PpottLfMjX-lW%dt1KBgdlVkc&SgEGT3XcJF0mbS?sYwCaNZb7{Nh73=o z!vOz9{UeQ~tXSz_eO-^}#IE16ImcU68C{QXoj9(XWlRmf%`JmO+R<2w@{j%PqI5); zz5|(Sz>*la;-28+AMC;N{GDssH17_>&JjI7)J>W4(=~9}m#pp{tdQ8~&) zmOA2)1;dSL8Q5km503DS=yfkXD#w^~UI*}6hp}a|bU96y#8o$omf<6LqB@K9>C8Hj z$8V)sC91MWKi|G#r1=|dLdB?4s~B zSmI8HWapy9WiA!?Dv!calMfEn!}!&SbdKc`D|pc|+&(<9lV+|Y&lnHQg>l!pR6GN8 zGRADMFfSxaADltEvCo>ZQh1n-cyPpkBZN|7?xZ74z)e}DBc1K_9yUIT`dMxK(@iDTerFcBvu=Ingx1EiN|T#Ol+4x7#eI)cnZ8Y`uX zqW#7QjA>c*+hplxrPa4VQ%RBb^x#?Y=nX8FvF>xLtjT6u$s&xlvE4IaHx)~N3@p6r zgf3*2R>B7w3O?M=9iY8)r`=#MraA_C^p+LM3g8;hkSAqRoKsVM;jV?rz=UBm z#*iA?qn&po3kR;+N|=wF?>XWRe*hZJk~1qN3|lAvXvy8 z7YTSu;2z;AHoqe`p{{zgTfp`~Z13$kB3DkQEJJ_5FKhjS{L*wLzsgPlZnSs{Z(*v@vtTEU zhfYAN`(&vS_k9b$Z=PM;+fi(1K820=Q@k1S-MrZoj!&4^Algt5~U-3Y$ap1ty2alpfRXf&YjOV5V(%6I>A1UB4l zsDptfYrz{JEy^M_o^8S`CkLJn5Ke-kMiA|4o1kb`R;e8R@$ImLkxl5PBOa_gRN#Ub zB}8;@D_y=e;Cc1x;~UiJ<4#-UIMXP2q25Fu+^wY}*6#8=l0M=za!eH(g?N!YFoZ}w z7sl{W;HwW}&U)uGMg(abHky@2GBhi(%q>Ubf4+xCxx**JchD$x&uZINnuNH>N77?Y z=OTYqj8gN8A^UL6$x_!Dl~OA!+OHk9jaBl^p;ch*OvV_d+3id42^(O|JpVxSuqL60 zb)FcVxNgjOuIxnqi7=O6-cT?4 z7*D)KwVsm7X8BWlv;491HhX&I276R~v;3L!0JhBeJ6jT9SN+Nmp;4cr*mq*_EyHRo zyc!PIxp7cz3)h)2TxYpb=SQgXPybfuv7hTq_fTDzey)q`VBxxMAN+o}u0*P9#1}Zn00zf2;Cgy9Jht45hXoP#dxZ;g8nVZY6^>1N4e3 zXT`lMJj~>X9_y1YJ2XIK5e6d%dj2BW=pkm}fBERE()yEFRa`*Edy9;oW;t=rv%?Yp z*HE|ND6%KOHbLJikw+E~+uU|55Yn{8gRiC=+=)pgK6!5OpTWt=T6b@V+(dc%3UleY z<&5g21stxt_hqHe9mN`fDI5N;@D9%h>w=R>1}|onTL3TGhG^m0 z4c`L~WfRT?ej6|gw^5^10Eb6oO{pOwD{j{)8K!l z{TcZ^8}Uklr9$6bvT1cIENq|2llH$M*V@`q!iTduX6C{Scs%65Gzqp{^w(l9JlY#~ z%46++MaG!}$YA$ZFiTv(^9laHfN7UWyTj|2MLS(PY53YP())Nff|rh^4Ihh^@^Ean zax8iH7%zP$e~No#_@-vI3>@`jfIUknc}d)3Xlrh6qQ4tn4com?4x%}tASE!)PMXk?SIF-x5u%S ziTh$J^9S>GW;giULcvQP0jmSfHz{A``Zuossxid%?;f#_nEsJ@23~qT7955O)BhYn z42}%74Kw|REf!)hGBn1+Pr1W)3wZfsGjH!SSmp>^lNbzPW=oZhcfq@4o9E?$pyeUG z>wp%SC8!QD$VSbepRDLWd_&p{FZr)SK~Knyxs$dn;v=n-A02Sbbk(`4T*1Jvg0U7B zu|GQIT%a)Uv^>V$G*;{X7#LYG__rauU_`9;T&BshaWlokWaG|XVuq#PtS)4f#_T_u zA&og&(U?a;V@?wk4&C`aOvI>X1#Vn90+N)p<}7j*g4rb0e-SEnMob%b1CZdUOHMK;GfXz{5oAb`N^J_kX5}Q z*V^ipU&@byN92n(AiHdk*#OC=jC*_89hHZTPufc>pR3g5{MJ4>Uz4I9;OE6w9MrYs`b%=?p~wk zpFzHlv1TsGgM|?>F(zJk_W5cLB>SDGWMmTP@UAImvQ$$^|Mx+XO?n?IIJErMT>c5TIHU~Q8Q~r&BHZ5M8Dbl*2vIU!p~`G>wYMn zaw#C^GG~bgmi0Tt9aGEK6o!9)L%%@!{f}DE&IfH_zXnrcl}2rfxZH4C7@emE?~CU7*RzceVNS>D^Yu9B7U|jEJ3Y(B zvan~U#7Iw~c9J)88;kEg$+QQ5AGfvoL${9fsbDvA6Td4D2D*}l(xfMOpbJidx1H~0 zfGCL?MwG-0k=q1Y`aMB1}51o|PKg?vr$8$4OTRi?@*WW;pWkjL8Ew&l>w)ZfnHF{8@wFcPmSwnh0Xs|jO3AvhfK~We?6aif z`@;GZ56c46&V)kDMzG&e980Ryq4YO!;K{duhjknNS0T!S*cW1a#O*<{Hx&GSkjkFM z`WA0)1m!%pg~Fu@eZ=#vu{|eiZTGdRveL17Lhf}_Mk_MbgY6BiRPsq&YNMFr6KLV< z*%<#1*HyAJc7oGT)w%q+c(9|~hYVHh&1_Z#q&*8SIuPG}Ef?+A@L=H{+$U=d`*4?6 z{VX%b(dcJm=3Hi2VqGB41@EV2RJ3~9Lq>#+PM(VyoW zLJWHb&y<+Qy*6$r*fH3+xfowDukiLZl|PF?ESBY4m}JWD1we!*d>gnUX!5A0rcEM! z5_iDg(sy|#AHF-4aKf{#q@ZmC_=%S%6uESs3qg61ogOs}vNC0|U|svN!+&Cb$%WvL zgN(ItmD6gFAj4!9dj z{$8@Mm0L=|HcI@!T|f2==z{!EBfr1#E-zOev>c- zD=8!F2vJd?lBfapTkbLfZ01dE|Fhr|z^$p>nz#TyIk#~p?DS%ASwG?FSC^a%Jl5-* z2mQPu_JpNm72X9uz{Mx6b*|dxaQN69YK>)8@hV2VNjUHNF`+x*yz^QTGx`xzD&{}+pxxY0x>zSmRQzCHPp_(NkH@wzHP(sx781_H$_diu6@PPt9(@s z-;&L0T!lFleeBv05GyHZ=(9u5t5U9BRHp(*&K^( z1^i?cMncR!MA9Qi6y*pMga6&9p2B%GQ&QpUkDVORnGT-^554hxAFb{q;oIQ79K4;j z>?kp+fU>w#t^#n=HiUxz7-G|KhSex>LR!2{o7vEi=mbVX(exr9vHYnV!%7U|oEhtA zuyn_kJCG4GssOzm*wI+%7{pc`LJo43U~ePM5)tee#pY{2IU!3>56cWe?!8u5iF$tg zC}v3QX~MUG>sR3?RdO#69o3>0 z+(EhuT%p-K?$+rF1>X+c;Hix{%1U(~kv-3gNJ1^vn#6%U7TUPU{cYgTRX#1HgLviP zBMf-2B7VUM-vyJ6yF7B$0HhdGr3Nc1d54I{`T*rsN0wh2V}%~83%Us64;+Ho2^oW| z<$s0#NESEgNP+8>W^f{d*P4g)-tBzVRe)#~=E^R2?%G7x9xw?oCegWFG?v61)JS{e z#3oi+3AP_5#VRJ&jyjMf6?E}JbK9$~QB7>Ru{{CY@!CUK;0$7{F$c%VyrF(YoP+hU z(_jP29h=$fV??!(*fjP)(m_^=N91z1R}H-CVP>C$?@V!$hJL$9cbSBYMh@R$c@v`+ zrVrn16z;{OP4WHDyWRaCcN+`#uCWIuAx72f8QV1O0Egc82YJ8eZARrcFvk+c;>fpw ztg9Cjz$~$89NI!9{wTB45CMrccKU9#?~_3$?ay9V*HivE+_$2b31K_?{JE}6%@u+H ztN2lfi;5b!zlo7L!5CtfA}h4vh6#ms zEwC*7SC8u;i+OdD)O^VN!{DlU%K88}rZm9Hs4AY3)!B9ORg>PcyybzKl?Pn4 zS<>%1Sw&8saF-lh*~I5$Npln)iZ9)Dh-)2c+2GmN_eUUev|yUhB1c*@=0KYN@RUHR zWkd6`N`LF5)=V+&f);19ZES|J;HIRd%VgzK5d5De8G~ zf2Ew_yZ;by&Om>v-(1<0FWkR}*~9IfB*k|U;@B=#x~=Gs#32$Z+*}%nPxS zX5ioVLj4i`DDbP8!RC-pCHBTj;|JzoZz=X-rPKYnZ_gRNdfHpei?Pyo{d6{5mPLKq z0UoRIaOuDF^N7Y#?u3%Q{^!0gWQfUt%EwAq`qz?2bccLo9(1U6PsRe-mF+zuFBr+Y zD5mk%tH*u~&4eu~AzOW{r0Q1*rdA6OEDJ^w`{iGTGJ#FfO1t`ErO|_%fqtPn$yPE6 z9I2UW!OK>HvdJ3hlAH^Mh@z5MN$MkOQ>mn9WJOPg^@(^*=Fi7WJZo(XuFy)W`?4YV z(cbH9+FAKz)o5=U;*&Qc$}Cp;`np>v^voIliW9FBLaL~Q_=`SQBF|%`F@p@gaJFy& zYu8xm57*tc5ncv*=OpQK$Sad@b4ivI)6EgPjZ#iQM$R7$dOy;HpLvDVb$a-zqwv%_ z`-p2b*_(knX`Wd$^be))eb+swg<7;3x((G{tJHogYCqe>jm?HE&s3u22a&Bl+)A>H z#7d=Y^v=t5^xT0t^ybIl%d!WfP)C1{TX^5Y-fCPp6Lms=3y{rX(hZDE_f4gA@!f>)eZwi~Ws zCOn{m-tG)>q86(P9p?O@qo@U(rL|>hq2prZ`#gjG3%S6oBx^e3|5W`|OOj7BiS2xK z0_w)h^KIZvkfZ(aH}<~?_Do_sURBsq>HOEh&Pj%jSI5OFk|4(SpQYRXqcjWKjTzUx z6C_-9nSGKJ06FLcV5>(L5PFMA*I^!F{V|NEPjB+{!4pu$`Yp`VY_^Kq1Gbcf-v&Ml zu+r9k4sm#3W5E7L0hI~TN7{m8HjfsbP8CM0!TxQ))2eDFtT8>O^QB7WY5djV&v3*b zv$LX*Q8!LzGxeSt$2G61+?Z%M8YvcxFR+_0@$7OPe~IDjI@2YdG2}1QG3kC^*?j2B zGMhBQAIj-JUN)aAxXZ!~FtEup?d3nfzqg=lelnHE^Mry@hzFZh(!ExX-DNZyV7&?d z(OI)66cj^tmkGypIL_w9d5#6#8zX@YHc587!C5wc0oaP*MVH)jz$Gf#9r}DWhr@AB zpwSTnIWQ748e^V>FaBnTpS-E#?Drap)5j&Gxk@lHNZSEsbK)q` zHN5|q5SyX~k6ZZcM>snLp6Tz0_us`?W+JlNTnPbzRp7N>8N%;EF9S_!8=g!v-Ho`x zR0Hk55Q-BgAOe|i>M9#A#N!>=%UQ|BjfmrOm;uhl+6uH+PO=Tl#~x)tx%`>t zja94({Sq1x#wz4QFrV_S=Z4gXqx>!W7L!9yLn90YGeYWB^qU%bTKTnv)T@`Ge-odL z$_%+xMQ5#{$u73)(Ka3{0=qX-WKE%9H13T)h%H^nXk)9Ui%jZa@DejAbj8q6k*spkY6R-LywMTSJ*RxPLvy;K zd~DL*0smEYVAPxh4{xhNjx@$(JF59BdwCAa3$`OmjEqSyjx2x4q3JPs)a8G0RJNnn zhz5br+2y$6vthj_FV?>jjowrXZ5TY^m=hAvr?w6;S$BIwla_jkkqvgRp(@0Ms)TKG z7l*^Dg!9InqUI_YPcTP%tnEtg-ef2ASdQZ|Sz) z7tyZ`S}yVYw!1^Ye-3WDkDWFl|L%D^?*5@WYU*USx0yv{>#0Gj%k;qVb#0!XgLQo<7(c{j zap=jRV9XHo3RqBN*f+v|uYb9N;mRY+iE-RfUVvY{&t1N|{FBQ}6tolMb{#cM_wfz616ULJp8$1o@{BTSIXX7n8IF?S_^4 zhzl%x2l+>sWKLAdLrUPAR~$Nc@L<`I(Xc($d3IurdFeWsK|K$;)R*U}=OrLMY3iE} z9kTOL{;qnZUQR@gGce+l-?;3^Zeve5W>TDOxxQ^}f#>|@&!9s;%Eb3;t^rZ<=(PN3 zaVSgU)pgjf4CW4I>DtF3E(?+!b|A=kpcTuG>W)yfMrVjhd^|i>bf`O8NW-&-f_tv> z(68==d_^0ODVKhqxX!F&2GokRNX`$J91}inCgch-_Yr3)e%D<0%C@R!JWO%~BCF{A zm@#JOduBT|B0Ketx#a(Q$>Hy2Qb|9M;o*_y%-y0z)(Tby`yk5C13QXF7zvFu6wJG> z!90@b%-dp+<}=g0d64JhujiTPkEeUhMoTL_oa;qL%<*u09oHFf?7M~V-mL3I@=dlT z=Q?NWx(^|-XX9$i|8Y&4a*byA8uRsE;hMBnm$4eBh*3Fzq%dlcYT^i)uY$DGExwcx z|3|y7pO>Qr?d5+w#+W(eJzj}5*HehF7Y9~eD$-56JHpG()}MUJV7wF&JF@-9gwHRl z)&7g&b$vMJ5!0^2_%|HEtUbWHR;(K-aVnj6?mG3tJHa#_3cd{A32epq?xf#b!x%6? zGex$o0mfy*vylFSx8810UHt@;Xr5+yE1&mTwjmX4z@brxX z6-sU>7P+Cg*gWqK7ilJ(>a`2tLPYyt8=$xvSokh)i&R6CBbocFA!C~gaY4ZoCaisR z2CDsc15Z@;Rq~MJTa8~P#)@&}h2;@kgfYbx(^gduO;mUqtdSbeo^rEOE%G_Uc<`^| zG+PwXSAU*c#20{_-5Cl#dGuwBJ<`Ewu72#O5uO>|X%wJ|VKnDq?Fdl{DjOvr4NMhxpa!T{R<|5^=Gn}(WGu@+$Kcvqc6-_10D znFK3b=_2D{pbx+{H#JWrJ!H#}8;mKmwSI`~oIO6Kfz7n|fRE_sT>%gAH;01EzzjrC z(boM##NQSQUhYS)Z`L4gav}Db2GiQun>vwYhq1vz*B$OAg z*oPeUW6n1nogKSQ`KCi%w>W3G4SFQc*F0i zxj+1tYQTn_?+w4FTaVLw2n;gGZp0U!mAC9?UeRAxfvZguqHbCBXYyrJd3bLAxwh!H=p8(WmS=mp zm;U9^HdxA;8ot3MsOyp-V|NU2;NYz<*ES%hJdV?`-wynUp5)f_(=1Xqqr`_&rMKiTj$veUXtaxtR<`y6A@W zAGY(w(wh8urv|MXkJeGdw5H**XIVK13>b@8MJ_{!yoDAQAzwM=m*XtXW#vl{mq|xe z*y|drsm96^BaO|`RAc=(d1O0}Sk^ey8t9{1o88RBLqI(nS(gx5M3$>v?hl0V^|d8KbwIa}_|yvaKb zwoU6LwK~N)$G8k*wG~#=iQ*`kodDa?o>1`KKDLgj->v&(1&bK&h0M}^)=yh(dW4rt zkMZtoBYa~Fd{6n3dufD7ds=0WDdvFQvr5cTtMiECl<(I9lTssa4LYB?mlQ`$0Jxt@LU`&h=PV4L7;Sgf-6JvO1j+ycE~rA!Esc)XR@@irJ~ zPDOk}uBU5k{Lj5Oz8dICSox_Jk4HJIGEgq70@~C8Jhwg+ygKlA*|=X*H_2L%AAj&< z5qFu7AZ`P`g0oBk`Y;rnB+snRbY-;J4n)>}Y2;Q1c;TS<`LNHO1xJ)O*Lr)Wq)9?nxDz#f{~L`iMG=N?u>1YuN2DDvW)U`ALnq z72@QCH`pfvLZz-d++Wi9J*FW&P_3%Ms9^5JF8hTf_Cq;Nwb-NM05Lf?t;)RxV zu9qBNw4ZJvrt4W=p7Q8g@Ysg%#*QJLV(vDuIX)mv5FyiK_U&yRZVy{M z6g(VSe5sy4wn7gUmE}w!;_<+~8OznN^?I+dPj8F&KLy6+MhD;H&SkwiS#Liyug6yn z-OD{G+%~?BNuQxGXixX)gvU$tb;NhD2yK`=+=jP8Z26l)gppbhjTX@T*=ksKj|~MM z{J-9xttXZlz3>061rG??hKPE0*1JY+jkb=>eyX?N?TGrAhS)mz(nhN43o(-8-xdT7 z=5=t6);!hw<69JuZ18IQE&OO$dbT3J2PA8U+oF-#Nv)3F4#xD$T#~JfVj9C+!utN= z-NLKQ)#RH+4{So@5weLW68tr{PDrp21~@oGOwvtY689J;)FY3yh6q{u1F{a9wLJKZ9P(`9rfcHMzoX5HWsQ;H$Yk zC$N^!L9f)-Q=dc>+vQ4>yU&#iNo@6M8i0$~KUSPnK3aSUazt0Bsb`4m`xuQ^iVU}V zR9Jzt<~??<_PpWa75e;-?>ba|!MF~q=YRI_(-QrmnP-oy>)2Z#HEtgJHy_`m{eomG zTi+$zsa-6b7hX8ogQp_t)CSFR8)j3ILgxRJoB3me=bFdEa?Yk(IwD(Hys14y-+S1G zZVy*~y8JlM|2^>ijvL3$juA`B^8_8N8jFC%4+SG-cDB)zS z#5Bp(4+WnNG$OD{{~*^vF9LgeLsO$W zlU0iUfPtL=UI1ZgdJc;Byy zwIkN@6?h0%u$dC9s)3KM>276hJAixm*d0E)t^?eU@Iae{vw^eMzAFnK-QPj1l62L* zKuU(U?!xu2U7H~|#==t1oDF<&?N#7j?p$~_P zPXaGFS@PEVBBvO7{?}{V8fu+Bn7oU?yGFbE6q*kuY zR<6Cnw@)5vqjn@=U6Cn$aRza62WASH(&uNW?pu6d*OeaV(fbkVg1esy_VkfYg|zM{ z_**6`tyQCSrB~H>=e*@?V9_=5g=;WYM)ny*Rg)UN+_QnCYlZN#B3C=C&FbUYIv_DQ zHg}1WN~#WMp%Huo&+|nuld8llYRKCktwFYvVOdgwctx@rs9d|6Ps&>=;OCH4HgM~2 z`mD(63ZumS2@Kg3=_K-a7(M%4-v#6PyT#{Q|A8EB)vnPq*^JB%&H@%_Fk(kb?{xvW z19S#56bMtKy=PI%*5DeA{H7|V|fa5ACO~| zrPJCMd?(Z-9@@;eZhV~0Bz$}_t38l`{0n!2nUDJ|u*kOK+E0oiP9htR=|!-)c;%)I zW7?9yd8r*P9Vh9bXMOKuCm!0&WM+D)rb&47{z_I_3{=-9utO7GG#WWueyQJbI!2`0 zKQ7{b+X*I9%Jzd?4^%(6BI3)ImW9j4N!_q2{NOW+8-X*5E5jEg7O98T(uMq<| z5?0$LwZJzRJmA1d*LNI8d`h7ZSITC`{pMbL;|S?oryy3#i_6BqW;@V5ME}p$WA~d5*D2e=zzbyT+* zj{Hy5xAR>Z*WZhL$k?)e^K2mLz$*_1uV?T}Rw;J&g_iXjHnpX@nq5}|NmBoF&8~D; z1XzRh!;ELWflKd&?N`#AS|Q)1c4>t#iwv&OLXoq&GEYdXh=LE)(lN~LB5Xkan$R63 z^1!PiHx)dl(Nbn7L2&_tH0$rV0Mv{$HQF{|%^`z*~(MjxdL{_Tka_27h|Ep7UOBv&`jotjjJ zctA0_!47oV3_M*Xo~1lQcN)!**Ho&|X&DAKV1F`iut3WddV(@E9vyIvh-(*;Z9VX7 zO){H=Ke)0W7jB>f$Vc-iP?t)y_Ts0(Uu@VH(?B^Y_F&w_zJe@)?yGIIw$)yJ_Ti1V z_A2np#9L3eCpF!9ah6n5OZ%(^_?V7E$TGp|zs^16Jhb!cS%)eVON9PS*Ftb)tNa?o z!uA9Y4c&{q1=xCHXaRbl22cGv*drS^Z$rOq+)ye###=Y8x00q^yb<+9mV%+aabwCt z-m+beZQd@As8adknV#S?Lt1|x{|j&Cc6oHwc6m&*3U(7(L#Vw#s&IC^F}^`Vaj5$V z*+TnEF+zW&2-yg&e-Xc6>Y)mitgX6`KoK6>;lr9FrJdcd&MsUJE+5>ujujF&+XXHo zsyz`gx|xtRJ&1Nxo*(vul^Ea8rxRY2;@smpl5HbAVqkxO6-A8WNm-FT)|@kTzl#tV zYUv|HN0cep5ZLUn#qTs_MtJ#-S;(Li>r;s~#A~@RPr+a8>Ml`<4j1pL-rQZ1*k*M7 z;t?V5akD(ay<^vByS8t3&;2~%nS|c96hV#X!Rd0mfz8E#(=JDhH>%*yL}P-x64=KW zrmDI{cbR3*7sU*)8*EZ9cw}@_qv74Wf#V~OY!Uis*^vVHBvhF|-lvQ!(4=Yx)YJC^ z^`XYMdVf&YR<^n9C_9bMl8|K>S1KYQ;t9VNidg~A6qoqgB9x9*Z z%-l>KwA`|HvzVlcLEuiS}j zstnL#D1}vV*sy)=I)zEyuGFf`v8_+t#4A;VSO!`Le9_@ycHuOl11(|@DQ;1RS z3BG&%m&^n!``!HvWXql4Ks_rnlb3mmU7oSw7SJ28Q@%Pxpnqk1xV$I$=Jnb>4O*q? z0xJ`c2z1q_vO%QhVsmHvR=NJBo^dKpa<9?=vA$CtXQRxR$NHv-bwEi05u2_Y^93%_ z71ma|1K(SrFgA|!&Guw&$!z=DbK?z+6vwx5$Xled>BU-EW6FJesXa*>;k65%u}1W~ z2d-1TY8sb+f>i zCB|T4nwsVI&ZtRQL?_W^k@VifI)`=s=RJeQ_V)k(rX$~WzH`3q{oehJzR~?^Uzj~l z=3eGyuiL6HrL_D$3U;8VDMHOj%&9HpWVTtDf|4zxC5&7$2_?_mX~R>SD3m;Tr;S_^ zijvjd646#jZ6=^3YqW$x$-1p-leXn>)cq(I`eLCAbtD1rgk}Gcgmqgra-D#>)H`+H zfZkiT5Owi)>vaE8N6$swt^2>v1>CLkK1bF=^Hjz^uS}?XYEx| zw(*2r*op|@keZG~^bxJ=`>>C~UYFJs?%F!r@*{Zk3^Z6HaD#VUVO$(EVWjgD8x~>S zx#J$U)58hb_M5py@Mg~)ug$#yU%9opCGfgPI;)JHw1h%{S1iuihc~s_jew+_qt3)Q zOwbPIa66GS?e9%DbJ^aN8=1-?J)1ziB+0#m!oQr{5ApxelN#^Mm2m|o_EHmP4mh6y zJRA)f{LFa+tOoq1P6TJ51d&19AdLa4IMdJeOlCeZ;=z7@U+zX5Z7M z?Q`uD;U(QDGV7kt#@oB&y8ug}ofG0RJ#Vyk>>|s0t+*E+swfsfIygCGX>3{#n`7{C z?iWA2@ijc*n@-nki#$zrdimQ}!+3E`ivx5@kGTOe)wb6xv}vjlXZ!ZrjJ2G#$@hkzjhPHxMPMzkE6JWAe%!1Fh4>H1 z^vuG5>yOVQvI@kos)D^gFJ_D|#*Wo?O7yQ+tS0;K6B76?GKOT{L?P1bSKGn&qQNu<@i?uBzOYjw)tp)tgWBq#gv_gSM zUgYzVF8pfN>4{l-`0Cw{NMszmu<6AwW#1A{%$n!oX7Gq)LMI{~y(`4d z>)Z_56QcXu0oh5UGmSFbbE zdC;Q>^&(!oCc+~Fc%5QVvz?_Cj288vX^)J_*hMST;r@K!*fZXniL|fa!-LTHdC#%ID2k&IT|AS8+-un<1TQdBy~zAekd$H{*iVs$Q`7-`xG4S#>c1Y)`# z-|@R8)fP+V${pvx%VN47-4Sx|hWpkq$)PQdukj^sS_7QEoe{iJ9=V}W)v<@WER`Bo zWj{fh)pa^>A0itwZ?ERK3Klr5rjD!OJ0mp8jxr4}b4#-Q58DWj1!h}*N!a6xe?bw= z08`Z&Y_O^_V_Xew>IoOR;&yy3*%IFd&tr<2t-1u-^{}wXWdfB;QLf^I$6pJnR`gir zAL+GN=3D1?FbX4RCY^X|&?a1HB(0B-Y9sO~LpFRnBlZ?UW4*!;(p9R_iBm_*e=MeW zu;AgoPI1ha+kdz1Ys^!c5LCTdSSJ4AI%Mmoi7H@y=t*65NKJy6D1TvdF@53Ju#Ceu zLduM&?Rumvsp3$}$!$rENm!2y=7UzYHM>CR0*wxD(GA6lx$6qN^Qdy1#A;Hnb1>>R z+P;~blSV--RFP2Kt z=5_ejV6Mf#M)PAX9aC-#s`iZ!a2g7T0)BBM7=7xDdbD38(3f6w-}EeSaq{~#s8bk& zTtU^#C-SE8;574MKmf-zz)DgByp%7#_kHnbccoroFciL1s4*x_#)5APStnWiKhp^d4We~_A4dY(YtRJvc`3VY|Tl;LuBV_ zO+oS(s5C0APX3=C!x|wcFd}Y*5qk(&?} z<}z;QOeQCdzfG+M31lpgv_jOZS zaZu6uBp=oo1`QGe^flPns*0J#18IgG`-LUSa!qh96T$Z zO*3LbA_~^O#Dt_?bmG_nv;88pmCeGTZPd?^YxF!}#H*D&yr$i7zc+Xc5KS$fZ)Oc@ z;brM@J&ktAJ!v2lx+H4RjwnLp3p7>;-~N-^e`riijXf%xnGyuv!Z>vR{#C1e@$Y!G zhH!;hN>?Vv0S_c<#x>@5so-+pE(Q%O0uS7jTrSO@zj~W)5@;;-Y90PnF~$gC3Or%Y z_xqs#lZ$KTPaaL*y0~sWo6O#)5Caw9sl=ac3QPPPDdTQAl?S!Z?Z|II0I7R52`AqCd)mm{He)l?Hs zpdY+qu*a@^XW-4#$G!)?PeOqW&4*71MWR0bC#OemsV9HNdb7FVvHB%Z zikvBqaw%H>NPPpe9^mZPRNVy2;;cucXdV2P#=k{5>m&6mq)C>&+i>T{yhz?nETKKj z6IutnqUd%hR99D7mRnX?Fau^A`jWMq)9upq<;0o7U8g}GfaRL}-`f9d4Rrijn$F+o zKG{7Ft#b{8*DAc9km`IoOTQ`KX7kyN9Q^66&OxLA;5i=mrG6e7cue$9?l}XBWc}2S;fbISCqyLx z$2NSml9@J#yxbahTT_5#4??5h#5Q=m<6$Rn)QLJqwvx{`G){eC9_*lbg~By;8#6Vu z3DUoqIP|fIoh6pGv7@QI*OP!X-UpuwT(nuXX*a?$OeywW)58q^Z6lkA=4 z`lV07&%YvJuH^FO|$okFHIX=Z)eZD+Jy&Mo{G_TG(SM@A)5Mr|~T` z_Ic)Rd()>U2Ct0j-XKQXg zMX|4P;FALI5_jGmKPXYMACy1_d~sO0Ge(@h0-JOSJN#WUolKluoJFaD%lQH{4X{V) zzWhjgWDX-omD)kx6@U>RF%wOKbpiDDxUYFSo}qWg3d!Q8c4ji2i$jma*?qT1g1UN; zT`WFxLy@AN-sSW@bq;=h$vZ50ADAVw*Nr)fX!NGn=Q8n#s|q>qMDg~u{n8TiP2lIK zS^5{8&YZ-RkCoX=;Gv4&o(CT!iiC*mOB%x=hvA&Qzz-o;k7J!bx&KEZ&q?25U&?y* zhzkIpy*YgR6x`yR7{sal98#E#i;2iIfJ>*dDPqDi$0PNE%@Q*%GYtOVwwep=e|;_$ zQjFhTKO=3|r3!mtz3ngLMg%TNLTL&->4n-@JQHg3%Vc9LDBFIW@I4D`8mEbquhZQv z$3aU|h*#i0dgBK#GpEkI%xuo(nBM}lap2P`bNn5AT#$o}3wC+{F^zhnUP^Ph$;qPg zy4K|}C~|F(<|!bn{Ny>yWY#r5mz}If|MMX!Nx&@8&R2-FH6oz+%XMU>Y)XWu)T>G2{u^fWxgvq=N{Q=N zWqS@Z)@;}_YHYAFtx6HATB@YFnJVFkB$S$fW6TCD6Bnw)FKZ}@`8lh`xd>8`ZgB_Z z^G5goiaQo;ba-o&a?N)lmERP}Psd?+(4%K~2lb;8PqclsARSSVSwk2+!Pu5@uq-56 zS|k4QnsGgB?M6#qf_Iq}32oT76xD3DkRmQ_v0&D|)aiwfx-ALCBFiR=8P|x~J}rM^ zikRBM33}{6qVaHxKzc;aJ%Z9$lz1h*)5W*JhgbnwDtunR3x+{_pp9(JD4&NsFAiTn zAk9un$Brg?(aVn!7v6T)og=;%JFchVBwV>?R;z7Qk~yE5 zVG;M+a5E-_?YhyuO0;2?1;vf-N1%hLb$HXz$0S=)lrAC7OvGD2`w+&k3ExjPrpe+T z+lZFRcdXm6&VCxP;j7@IpPk!QUy8pBY(CZ@W}Z|s5%}`YabD-jab6kIEaxF`H5pTq zqXl1)zF>xvVCQ0Co;bS=df&Kpbav7C4Tfqm9$uI zMI3~#UU(Rvl90N{|HcCe}-AUb$rXVhpVP&q%{o5h_cjG{zyq`RUoG2nx^pgri(ZU2eszn53rIJ^9_B~)uLhS3If$I3U|9pnqONy; z*b^({<}AT;&X(?+i)c?fJ5iV^K62dx-r8*JK;}CA^}xPP2Mcn7`dgvz&%%@GZ0Ktz zi64SbK{tYL<55YdQbH>_sep8oT89|px?flI>-FBMu zO8U`XG@>%mY-HeD$k)Wa0no$@-PflEIF|=EbF`T}_Y&1Y{F*OvXr*7S^M^OQ*h;Jz zbPpKJZ4ji@d}XrO-f~o$UT71DYmn~ffInbcK}(JqtNB^Ku9NX?lr)4{iLCGS?nnE0 zNQT+U>)_Y3h_5x#iCXhH_-HM&!3QuTrZdId_EdZs&32MFtDX2LJ8VRe@rWz3(^`mq zNp-9-Nxa;?0rTj6>fv^?OgEEW@^Sb9`9h%8P@y&LkeTfSMOG7yt?S6yy`TlMrPz`% z#}fm4x(YxWvIe4*e{^^DBW^7)g+tetqI4Nf5M+!sL_K=zzv(}V?}f*KEQ(2tI9lzr zj^3}?(@r-l6oXt0BwF8LuoAln9`U0$2lM(mO7$4*|qtOpzETbfEhIX_hj^x7QPF zs$F|??IiR|H*u1<^i3KiWb}x=z(vQ)rO9FkVoT5(@2k^R`fjt~w)Cl>)uy}g0DNgD z_WlS}jWN9xKC*cba9S!A+!0nqQzSGJ<4+M7z@H)yM&jQ=`GsZ)TvQH$9^^WH3+!l$n%2>#X7CPnPIK|DJZVroq< zrxIYdc#ga>q=;E^-JPd0uKQP0TzYz{vyq3?Yrl8N5MNC9R;u6{%OnaJAT@7z_mPz8oHeU2xzhkU9jUU%m0$M`RsK1KY-?y!J;ffWJA0)ZK2ies<) zz32Z&@0SNu2V%tR0mQGrPNSkPPsDitr`=ocSM5JqUvxuT;{$6C{~C55hZq0~L`?E4 zx8U?p9|tk(UoyHLW+@}ShxoZmF)M1c&|jDfA0KMOO447*v9HZrWv_?~hSy_t8%14F z0ME!_=p6310S81J`fs0M<5>qEKhYP>C(i+J-KJL(RbD>j|C0vf!`-2}tyo2>F zE`Bk*^j@-_>vd(m^Ay+mMQ>QT%5|=HUgnB+AEdv)jA2C&VaE0a9t)7??1lE9=PVHV z)808-{V#L2;{VLqKd$@KXscPw8B^h%GkW&Uy#3&Qa+m{5OfWwuhB5H!Y~U+sK9_*= z%pAr|a3ERyMY9?-4A0#0!u%X)$sjM+r=oGNtBdcwlzzD$nwg_dCSfOCZT{!?8gPVU zTvWdnvByimmuOo*7Z!*!#bwuaAi{^n;v>fXPD7S%>EtVwbo_E14E#&n1XiR+v|hp; z5EJ*quW)8*f3AT}V=Qh(*>4xHitzVKrFU)IHg$YDc=0)jS@qE8177GtaJh|#+fQwK3XtX47(Lp32U?t35j0DM9P>SI zOocQa+6N^6!|W~#$ayu#Nz$+Q6}UUe|K3u^9XR!HGZVYm@j9^R)!;Okjr*l^+`r0} zybaI=H9q^~%fK;DZ_8**dSR}8Ke(ty;Be+7Ht7}oOY;&g?UzpJw%VDv$&kaxf_Hez z{Ic|}?#HJ*?#H3ciyJg;rugSKg5+6zUD|*5jt_92-bS90;F-mKCsya&^WIdlcpLLU zHkjhVeUhqNDU`{2VJp&Ty%cy;v6Na_3_P9g@p*cZf|l64V|xkwjTP)cU;xBbsI)#- zuW2gpkJhQ<{I4-_zHOCO?1JE5)$>l2nrlF5pJx8H67=?D>N~d13G;O!D4&5?>?;88AAs&-j~Q_GF!{x15bbo`hV%tV4oDa< zNB`*WfM$~(n4WD7Ux!(O^?Vumv08CoeU z!VCqqbH^{R;I#TLLXB_(UyP_mFN1dO25yZxhJD#YDHb#ILK_P__tMlmjMZ63xfV!xV|vc)TXV?cixq(-Mf)vRDI{uUfl{pB!3u6HJRc^8l@|G%30VcrXjAxM;g*vOc77D*y!&tMS&+GX{BNdd{A@FIEz-0NC~6vA9{oe3)YMOuC*Lp!&lOn1>gWYn^mRhB#S?V{#p_e-?!pFWk=bsTO#JmM{z@&)T?P11W zrQe2TrK-~+&%vYZ9-quUC|00k4m-y(!PP41m}%lH=x#b1!>0Tuo#N?0VIDJ*hS^c$ zIZDrMztbz_lI5EF<(ld38k)DABF@3fppa=Fr-;98n+z^wG}=DcHpP_(ud+S*n=3Ex zg(h+d*--xAPJ~~3-$ug=tK@ckHCHoJoO*+vVGSwb_t&5^T*+2ap6XJ>v$79!s@vE? zr9=szXeWM`2(I1EI&j%4EnWY!OmR}Vk8nV>urwNRSvo&P#DoWLkgZL!Ly1|0mKb_f z)GUoo6o$LEbt!AYl4^_P8wDKg=i&WQ=^T8Xv{axywV8Ew=iC5&j!5ecYo?3I`skE8G5nk8Y{5oc@E+^WcE}g z0^hXh#ei1Qi%6C^im75}3uzvJ+V9k}zs~+PS1*3oLNUc*Wjs9AMVfy(z|a&1t0=<% z7jXnHw~T94(Kn`gb#s1bV_auJ&#!|v$<0DP)G!+2$Omf3Gx-<|NiriejElT0kmjqG z2l#3pMo>)B9dIwOM*Y`k3&l9uW>9~>z5%_1(*&=p6;WRe7I~v91UY?R!>jP&2YkBd z8Ct#kW)*H8Hrjx*?Ma#{W{vWu=K!uofRm+2r~#Lra1kHzNQ()&jO0;Rkq}wrEmezo zxEGLr{!YH7opv8##dF2;Z|WN6!>7=z_P4Ep&X1nw;?z!f1L}-oW3W?nmR7ga6yCVw zdE));DAeKnFflLJ?Ue#8id>xE$5c6M%7R1RWMKKwAFqV)#-ogH}E zM5E6Ym%K$cAfyL2zZlqEO$h}TUvt5)L!o?JQe1d-ffi>`aiMAfv_4ae_8W)|{tWmS z%mvs)Cof#^1NaZL-yYq>G3@62g=`!zXo2hgpnped4yl(~dB{HNYo)2t`3s4+MBcG~ zFxR54R%$iMIXz=U+a$C#B2s9APGRZUl5Y_?#@m)6tqg^rCi=8A!rSV-rD?Z0>qTh@ zJ&;7!182%MX?KE6nwp65F07OK;78k%$v3stUkEFg26%?#p{SwL^8fcQwJVoiOoRs* zt9Rabj0pS#`@w}rB-`3j>BTIPSu-&YgNGET+#Jclqs;h6*kr~>JGIC8*!DO3b^6^A zs|xbT+o^%AP*n5rB+ClNsc40jD}6=4d0m576Y`%;|Eblj(N>Tpq6bwqtZd=|-{1PV zpDQDlu8^cRtdBWnzyr;Q@eS)r#~7p%hL5Hxpc41()DMg zEaIEcU$%6q@H`{FCbvyP+X~xGl&Vph2p?s^_)GpPr@PMd3Po8CfAl^EWpR$_S1es) zk-879#^LW~XCj`9L~63^4<{Tccsl8dz~5gxqfs{jsd*@wh`+ybCb$rv$b1wu4HNUY ztD)bVl!iO~mYJ?3rorFk@vrEke*IV%Kp>$`7kuk87+PUA_ObvhLwK>t8OZ6L#07i!5(L z3il-9l(EOIb(eOMHKGEkBBT)Q5vlD+afp?9t$VYaQX`cwr<6$Lb*f;i&l#?DKiye{ zz8Jj`y+XSwK?@yPqH?Q}6~HvBqbXYUyV2_#Yx6RDc5V#I^%0kYM^=@51wPd;O8MN5 z2!B}Rm!Ks*gPV8b73mFVQ@xw8B)xvHyNijR*ye3t7JORTl*RVGksS+Dy8eSzn*KbB1c&=CqPm$%zyz*)vu?HHf8u>fUNPRlSfVdJ0tynog zIcRFJi~;^7QF3&E;&RPNsNDd~Ew)se$@-$dg9~+l02<+yx^P%ru`ycFgDAef0{_QY zXcXb5KA;t~(wqIEW?Pa!tUW`_Of)P(p?@+4dh-UsS0JCLTJcedv`!dCkr4@NIF4+% z03&0>$PeK+8oH6X2C~N$J&0Nl`7ptYb~kZK;HL<*u}E=C(g^Px2m1?>JEwx`Crl`b zpmJJ_IO9Vvd?st)ADbYP1Sg@bo;BH!;+sqIXg;4iNAM0ckZ@6XWTUtI*C-boCJL2x zj4`M(OqR;~3*mr3L9$I$tGi;Tp?7W($Jw97#br%j13^)(VJkpr{tmkg4xI4DdpMLOj z-Frh8)X;5NQBU`u$NlFI$ljZtoQUuH-H;yj_gfOd9f+3ONN98P14h1^=5X%wVZfEf1uKH-`L`0-B#v|xKz6miV zU)a=T!4muz6Otv)U%F_&U2`n>)~m1x}(0=mKp8XZlC9>@6~6Tuo@`O zoaqce-jW%P`s~c<&N%e4stg(llHvhaz|-X8_XxT?(K&Kw#ynu;3=9!>4_ z5Zt6%c#j-SmBYv1=o6mWsDcSh{E2H6HTsNM*8mSgI3a`wu#G*q-@i+OS5Dl~!_cL$ zN#-EzxPCKBH?7WIlE>R0`^}wHI8x=3M^6xfiGR*XQ0U2MK#*WSlHkmqMH>NGf~jN+ zO19#+9lsawdkH@qemn3h4c4N?b-8*M(m*egpV@ir**rUBd74pin&V zH>4av^z7%lTFAbaQkhO04af*Q1(C$=!cfK@cRM3+d%{`>G_|K`=6kTQV*UO zk|F3tK+lWPVf>EZcMQLGqxlVlOAt4SB6dKpAVkxUhIydV_)7mBPv{!>G9^B&2n)ao zh~t)O_7}Ly^U#0+Z?T+5%3=$@d|e z&o5o1X=QP!V1=p)dT88Avs}~ZaTkr;Dc?R4PZ&HXT`#YYI~0$7G8OtKGo^5N-&sH6^;E$J{?j?e z^{6yiPrQI&KaV>CeY1yVp@eh?C^c3O4-1Fh|0Tf+-$6D-+o{p2X0`!Nyk&j!idP!t zosom`jL=MY=foe}5}J_!%t&DFo%#3?UaIfR$IXG$LOrm4M)QPAKVuHGd^Iy3cIakg zVIJnqP&h2`!f&3D;T-4U4$=EB3>4#8kDDD?e4DW#CJ{rqfnjfH->|n-!6e=@dZm-* ztagB++VU=V85)k4!kIhc|H&DJ(NQlI1N@<4L6BnQKKBezUzGEc=K=mf2PR8ljB+&h z{D2DbOp3bT+o|!@cB-^_IR_WKF*+Yb4IKR9@cWdNKA?&fmF#gXq8O;_nDhVdHDW_r z#-2KYKx*8e>p`LD0>W}0gUvGksV1p#L89PxhULu8FlQ@I{O3BxXwE(&<lDD#_{*2m#*=uE5ve?-#EJR)iF zdl30hg>FU%C2S{MAAYwAT-`(hk1NMleLE_I2^4Jmo^;+&LdMzppEhuTKX=A9E1dg^yFX( zixR>^pwYPG5R)hwEu~h@nH9FQ3=lmj0NNb%ed7B(?3^#vQ``rVApsX@B7dv?upJ8p zUK?d->kjW>rub*{uR0)=A=Xb-9M^I*E}(^VmB;xyICvxtKnz9rt%NRC0P6I@weHV* z6|+)j+=AvB^=}47SY~Am0U1|TrT5sD2AJ@TJ(dN`q}cQ*dzFc8Icn0hkoH@ENzn{{ zF3^4pfRs>?m>Pcz8nI^hQK5bavz(aVn_n)aBqTvkYfc)xxh5#=tF6BI!N{j3gyhqh z%)q@O5C_N4ywo0ra^DrFm`V8t`)9x$%odG!xREqq#mov}M;@@y4VJFi%NXO%y4|1} z_e$f;JgA*L%XUM13+n@0NK1NcuO%%5kq}rOn&vTlCB++hL&1X6kP0t`wRtEFJ(%Mo z9vVPIorID`s-?9B1t7K#eIk`9%y!ak;hh9S-X56yjlA+k)Fji&*5=uP5gg1>I^OQR zkhKgk4mcL}d+2}d0QjhorW%W9%DV#3>66gMn}qL{FTz}Z((BWc{b+68pGSN6L+^#< zkD&*Cw1>2T+C0Q_Z9JHhAdGW)Td5pqwX(UBK~!DMXuD|x@EDJ=Bp{xnjql`_RyyN|eFfS#A1ejHw95rfE&$9EdRJBBpq&Mb@t=1n6*K6wy5-t$g5J^)1r z@Q$tG*~4K>DI+@;Id$i2I=23h)CljHekJc zlhr~EbI=N#cs5oz+jOJeNBm&GQx7ZL{t{?l88(7`*mq||eZ;pAWgw7t2565A$YS2W z*KG$S=3Q~(*ZYW%LQ?@0hn?t;QrM))Yww7Kj);%=SG;p_Lag9xCtZ=Megj4`1$QpA z8jwmEr13(dLEMa#w@)AONxT#M87I|2x>jD6L;C>r80F`Kch+px-PwC&boPA2rTyN0 zSG&PW{dhHX@*8&KO#mfrlO_h)=-d=3gl^~zh6VvT@xGRehz0tCnP3)d4)_w0RfgDg zfPO~M0;I1Ak66GWJZ_)<@r|{>el%kEFxlRhgVHLBjcqCd^eHD=EEYarkhWp|DH>l% z9?^Z&eq@MX9Q8Cu?&+39{g7lF3_-s(3(eQkgsAx(Tec&nA+h3p% zX*a?0m_rGzXKkJr%HBPRzu1U#q#E6;h^r-(gJP9e9=k3H@j3!IXiX2Bh2!ge#5T;i z_v{>i+;X;Xdp*304p(9I^+H~OvQx_{JA-*;X8@k5^w1u-X|KgtzQDOASz483Na)x^ z|C%;qWuYxd)GEAr;R|`5bD3Z_%HvC^wW6Omge7^ai+t@GaoV{sc!H&QF3Dr{mC`F_ z-+W4!NUzW=0&0#dB~5>3S^?z2HfaPF5Z?}g$FR&x;r%yuuXnYf4V*xi?0)OncbD!akkkwKN-NqyaO{+#%?$dUwN^AvU^HiVLAO zFAde^RZ6As&P{t(>kI~ek9D>_M_On$l)`2K(eGowEo}jJ6r8(P`11V8uXoSy+%1GZj99nII`NitDg(hj4?32+O13g`?im_jdG>^xzPEq5)QC z!DSzJ7FoI8mpHE1lh~CAA&iZ1p(@}(NAR;r%@Ks>5O)gttd2JIXZ2IQf;BJnD#km@ zrO)O-VrDGOyA{SJX-v@ZiZYa;Svp9}OUv7vG_JP=KasPBxB%kJ72IIk+JCMc3w`ZBWGeD(OYwR+{L; zja8Cv88dByGc5NttmIF)anhJw^=kI2=^+XJ73bC6*b9rD zFeVj}U=II!c~UP7a?u~xdu_tuKe!1eBKkRTHBQ?WSi%>4hf&U%&m)Cy?WZI?d@|W?K{In@r{AIaQi~HPQyOexbd1{sr z4oxGboUM$gfyA^jvWC1lP0uk3tAx6RkAOcAY1hH$PlqGOMSlaFk!VNyU1`vwjKF0ZfPO~csUc97-7-yQuy-!zD&}fTDp(fqVwloL?W6Qnl23sAh2!v3;HSo~T>6%0 zV>J#wHWV0KNq%O}9zYrvHQp4(g&`Ypi2@(S4^| zpQe5KQ9p}&m*hk&^by`42GlpSJWG9_K^mF|x#SOlQ!5D6NnBNaSQmWi1m@rf`{A54+a@eHd1NdFu`h~ zCEm^hEs>}}97Ps=_UVY4(1-;xz9dqsXiHy!5ivJ$QzOcpA$QEm0T zQU$0?I{)xNKk^Q>NDN+o5iN)toq-!FVm;z=CR~Y7n#hWdIMY|9gVFJ*3CCAaAO2Uo zZ{he5%Ut>EhGEl*yKOxp?4UJ$K_I@sbdJ7!8h8gI?l@pK=0vhr54N*&z*`13a}1Fg z=+5)rA$?K~`e2WT<&yQkM(o6`O3^UEdxURCUqG9v^MJO|2lFgpY=R~Z)@^`i)u3iS zmSTgP&+?GqU6FEvK7$wI;Pslsi_+uKjNwoimzddiBwru@wscJE1`SjqUDD<+O!uXz zU?JH@nreHQO(|AxQG+z}}%3EpT3bKt>wUue7SDy;2r6_S4> zx;K{(Fpy02U!!}AF(R4~_&m0>@HD@$Dr@HLrOX>mpLB4XCY^)*L8r4E)=MlnZ-m?I z)X~3Xdir;loZbyMxyUz?N z1TJ1meU) zCV`pDmti;XH4kJi;Gd1SFM8H(7;9JcjxS(cSl0rqtASt=@g`DE6MViY_qlv)Ax1&4bpbJ{)`&f*kx6(h#LcO~h0EY!1P+ zw`C4Vghi9fB*w`R(Fmdu&tEO7n@9_`9B|^`LJe;Ju?+E9-RZB$+(GV`A0ioAB*os1 zkoZl2C%ATLYI%zrewS-Pz%gZTbDv$HZsEm1E{i!40p6TG(uZ>;Zlx4)=_o?Qr3F7; znPGo^Lf7L@GNF+@D|#N0Jzrpk$Tv<1AP(e2`$pVtQWW-~uAv&%g%wQrSD0r#VX>jW zXVhW?ENMvQaAtBvy%nD9YmxGnoRv#1pycdi+Q~J!hnR8nv@H1!2Cn+=&k;AiUOJm% z6ff|Rib%hAkj`Jo3#`i*b`{W>?qUan6Pb9oQv*6cf~Q&Un$tZz;?{XAjc58Hi^)FI zACo*6|4vReWm6>XTMY5XJ|RDMb{poC=Jpb}Pa3SR264K)CGfcQZzT@7BuH*W&s>Gg zWkCpW#x>`e1l&W>Hfb~DD_*T&GDB3DX-<#d3o`&8hiWo7uI2KZ?Xr!28Kcw_UiyT~Y7O;ji za0-i!Z$k3@U~wbTyOCx@MX?gn?^onbUeA~~lnZs^U1q;tm|RD$C7FQ(1U9t&$cQ41gw27_^P0(xSvFX#oe_ z%|xcWN)kBom0u+-M2R(+L+S~n(hWRPi#Wx8CHVX!?mtTA?4Ns_LOmi{w-JBm)GQ{*F=ovaJm%mlE2p$HU{4488(*b+G#s9hDFo@9=^kiZR11X zRS!`Yo^PHQ?5Y1lr&iThuSBFaoJ$oyJ-@kBT4;y}j0{4aFO{qXrBeFZQfYoxDdwS6 z5`y6;2k>iA;&PV;zVJOskn!KAc6n)p5%4O&GQh{-ytH(qT|@Tt-+nml2+g)6}#QKG|2`mu`=cam#(u8C|s9CVdyd zy72FuE1fJ4ehVnNTk$sOA9LtV_1ncC;%c~kibIey98&C49a8RNAY~yhJ3330_{>3m zYf_^fa$jXLYeZDPx!&87I12n$U%K;v;nRORz#-qthO95KvR5MU#tZ2e!^)p6u_lAV zLll7bzmU%(PrqGkLi1oTQ$E-!5)6X=h@njdx~#=v-xPpH=EB4_KLRp1?gMJd}%`qG+3-(|g<> zdSY$&kJdvM&!X?iXAbvDOCLyOWAQFM^+Zpc@Ej|i`G4AN&7Syg?GAW;D4zO%+JU?E zZ|!z?JkhZ`wD^J-@hv$!;*r`4++xBa=zpxEuRYv5V5SkWW{gq(7LWVao^cr}p>nXN z=SZ*gtZAf82>fwNzvBMu+pJmfc6`Zfm8#Llp;L9%6f0DVr=K7*z)tz)WgH>S3GlRj=Bag*8H`6Pf_}? z`vp(8TxLfZ**9)QSpmivXfUDWJbXhQB3vwjiGa;;leKj9W8M;w ztHs*OwQGkF)e<^m@b+x!x({DuKu%-0$#`>-cj~aF!_e2oF2Y->HSK_5x34@uuYu-_ z%~yb@Fw#g6FJK;TO8sY@0TCas?ZM1?Af(OfqUp8T4nYW)3^&L z2C)v`*!W>Sajnc&19}+n3O?aqGX@rwQKsPpNwa(J@=o(9(r=X^u`gnUJv*$2h zIoK=LQGZ{I)_TXh5B>Rap(ro1Vn6gf3d<_2{|L>^qtPBit*m=9?0ymL;J*d4;wywV z(tN88TIf5|Znt9{o*7XasP_YFLh$_4Bd^$RD`D^DZ|V8~wSxoewU?2%be&7P?C*VZ z=lh_L;!;6Zg$jD7rLQ?Cci;F=oZE`Oc<x0vLXgV_oy{~eN_GwqtWm-?XV_glpcE(a7wV^Jjkc$3hiw!~ zkZOnBn+6!It==0&kouw(SwEof5!a>P{!0kW$LuukT6yQ>bG+3bv+QwS_pC27m8k@Z zgFx*X(x8)zH64cU;FD#LfZbM2rjpb3-Zz~BM)o6gIX)+-1KU8-ms*3~#sKdL0R?L5 zdn$>-Iu{7rn>Se(Wg zRx`tH6~^z)({A<*S-XO^kS;@e_ki15jx*B#v6}sgy}z5rjVEzN`Y)>EuHsHh)8nZv z{h&dxdnldX4_!7(PPV158nZC$&gswW*|)}9w^pt@mTl>JS$=L6o+}-FZiQSI3))Tg z2b1}F9bZvyU?xS_u%cb9fD#9Vfc=5{b^C|i_hYW!4Jwh}mx}bZpdE5Lu|G}-KH=4b z$?)h$*R^%cu)A`IAd7dMDZd92x;t>#gs&_a8r=ox3-DjA_1=c3S?uk*wFFI{K`q&h z!|Ktaox&K&Dh2SYK#$!U08g}YJvvwzUkTGV#-89hUS`>ur|PxS(xgT6utOebs%M}( zz+!HKVV^I_&~aPP5`4pT+`=@jETo$$jZv>c`m*FREu%$oG7Qi@El2SlGwD%D(XnyC z8%+x(Mbt)t`VSmPnwmzJ6@hVi{S3y;B*1^nvuZOvxt$I0CGts@=}@d^oQL$9|#e=}QQrxS_-DN0CkpQp@ROl5$WZJ(r$&`&h6FXD4Kh9{P^M z?xoWEK{PuFL6lo8ZB9QS=M#}9ozh|V184EKm}xrF=JlCRaNwv62c}3Ic7jdL)BE-g zp3aFjMag@a@QHB}VKLtK2T9l`)(~(j3Dcq0TLw|GmR4i)GCCp861N{wv~l;qh|JRU z3u}Opt3cdR18A#C!2coY-FLM2Iq;s>1vo`d$0JQrKl(1Kpr9E`8*<-lDgtltlr+}N zRq9}+?%z3<$Bu$LAy-(7*lHg4LC<+t z@tg`~DzQs%dFYL$QX%3Z47m>@>g$oTBhn^0cL;Uw1|5;M$hivCwXQiLZIyF-klVEE zh_qeKl_IwpxfkTzi^yf5mzU(+7UUj8&L-!cL+&BuO66P*-jIqnydvk;AU7MiGC8*j zIW>Dk+AZgndyYu2DN~{00>3J-%i_p0C`OrW^n)ZQSI`*&;W1Jj<|EW>1P(XWY_h5A zNbcl8bad}}54mS}{&l_g!zTOZ^+v1&c_g&nLpZ_zzTPhl{Ofve8TkKR@9pw#x_7+? z=uD5UcaMC&?_KW>U>Bd(v8S*`*$VL6$f5~eLb|`|R2$PP^~MF22c%2MY5UU~LycCP z$jqLlg=xp=*^dU1ZZg&K_Xg^w9c;1V2`tvp_nf@c8vB@l~g#! z<8A{!c}ChaiDrBVQNt;>WfJYHA@}ogZY%2EMcpPjw;gq@YleV1QOg&Q+q7&5m=on* zLT)p1PslkNavA7lrJO58?m^_1$+=gMdkDEDa;^+-NW~k{<=k%MW+OLm5?sSLk;Nr?*4RFOa6*mnpIu@;<2cfrTb< zn97y#)1k2;R`jr{^8&BH%KE^1ldV*~?m^5hpBiYNiW9k0QkZ^~&uZVc`cqPrSyOYl zel=na1oA4tKz(-l7`Y+O6xp?*8oeEsj!HCO-)*#SkR_y z^N(Z+>JV)f2+0}6XZ;Lt?rWf-J2>0{Njd4>+SmT2cBhmn`hrVN_|A@Qnx#$HMFGPlh{xE7NOoNW$MK~@ZpAQR zeuU%w6FA;iPMT|?^~-=wJSox6BA9K&PGcq!CXh>(zWd?%Z%B#RysY%n2Se@-IiCd@ zflAI{KYt5+B3DqNZ4G7=-sv!7L+-z$G!f}sq@7564C%;i1pYA%b3$MB6sX-{_heX> z;wC8(8`RM9BdEdwia_7iNYZK+R+-9^z)m)%b$yDsN+a$qh^&q5sl%Dsqbs}vT_!<#d&`{G z)dk)24<1398G-*(vXYglzNJU%_V=%NQXxERA9h=ZkxsUB{UPlz>}ow2eNFw4`#5;A z4(N=L2H{Q{#gs9gREbZIL}M)yWD6?NC{u}BMkbtu_i2y=9F4<6DoiNn5PIq@Mdo+VG?zL1XH1!oP}f!m+Sl zU~KYJA4{()6p32Y><8Q~Y*ZT~G5_N$#~LFl`IF%|H3Y%Kk4IsyP7c9OT@p!|ApOT$ zgEulnqvEl;bP_C{{Zdj&hn>nO|M}p4DPeLtvtLSlx~=}L$eM^qnfDW7p&jnT-kIVl zgjNWpJqDVSi8zVyZ7>{zn}IMfq5_V97NdPJgxKCpPxiw1APIQOW&uq?PZC^KcytEv z|1(3Oo8v95MQK0iX(o%x{qB~}Lis;YZu<}A-;5~aUNmS89sqc?nLX8L|J4XDzbmun zx5)i%?vR4t$7DE$%q(J!|^>Yq+7a+iC*ugfO;e;Ga$`P6gddGdtvV zBc6#8Blfrj%s#Aj@C>}crg^n_=E>fUZ{_c*gAXE{NO(w)Ph*HdS*fa2<3yesA}!dN zj)$OKpggWRp*}g{-ZQ}OpM{vlI@jyi5sXQ4oaz5^j;iuZ|KH}Q@vmc!5;TXokgx3c zUU@uL2>5KoeSV0YX`6p9GEaruYyAM2#RGGVE z!mPfJ^Fg;i`o_!;x$7w}*W1=o{)Ak=c^SQ%^6%Vj&ty@)8hJ0TjFIb!{vYkXfa-VO z&C~N6;2)gHqW6WM?ghE8hwyGDE1)q6mIPF~5#wa!aZs@$$9U1i6cs$cY^^}Y5yU9DfGRFk4adU8gHUB%`=13;=zeD-JLh=Z8?8u-iF-& zdr#iBcF6rbo#4Bx=6zE;?9xVe2wHp%%9~kxhue$uKQs}rj(BPG<$ncb?ak5GT%fk2 zd}f-rv-jj_-s*^ow|d*#kw12~Z|{m6#@DdG54=2~10S;FzZF(=oHJ;#%D}t$IE6EC zaUk~mn?wGtHI0NrK-!6(N``GG9x>0L+o zA@_Z9iQnB4@B0(+{y*W}>|#HB|9u~9LYnZasTq}s9}y^QfVGTXww9SB@P8p)&#BP$ zj4bnc*JO*y_|J7FTc({w>7l{r@`vwHXz(P(Bor)A zIpC#mphW6v1BYpAfa^Hm)0)-rr63_%$IK!3OOjz)pL1NJ88CIoV-^CTZvfoZL($mD zHx1csgvhwcRp{jP;g{{=nNQli<0zN>R{%!FFujg#3S&96G}y{Tuy%|W)F+v$VR$ts zzZU9~7TCuRq1N!9hSuw#bHThG4M`yP9zD@I@U?UdKHlcw z&fV=f0BbjBzQGSjAj=Q3%YuCnUHXx|k`6Wvb0 z2r-i(v4elRZwh{quC4aNN!h+}N&24#yZTZTPr_dd;{&Ne{sH8xg-gOzmj#&JuzT4s zboQox*;F_G(+-VheL8>Dt0|>$W!=@8VrmH6&O=>W2=TTRuGLm=YPHoXY20BXi>)P+ zVlFJ{`WqKGobW=ilc*a7`1cb8m1~)#@k1=Puw|0MZ(5jNLZ!90ZMlY-euid0fsMvk zpZ;eUzD{J1?;q^y9R^lQQNeT5*Qb9L!X{h}S*&9d-|n@o$pUZP6H*P|eG$STNFaR$ z?P9&K8!4@@N6ypN)+kTGkA00ldOmSV3NVkj%ZG~q+ZphI3LAFZ{ubI$-xex`82!rh z`F(oG?7Brp@uX4y8{gbyK~xo*pO1!EL_1fuMevs+yfdS8g)Lc?en+2-skyAU>_;u4 z_*)UTLfGUdbxN1+!N=3R=_jqX6u11?=^A(ovGiRH8k8j`mcFlpd|cdgtz7yQN~g(k zkiQ2R;PHHl=Y{jENc<`(J&-hOfC(+?vT?*`1O<^zG7!M{f#)X>W<_Vzx@O4z+yM4| z;hR?I58rpH-Xv2Xm(~!+74RQAy_T*tIhPJ7^4I_~-LHwA!cEam(hHM;)h#C|Yvo*) zt_Ri-O)}(OIKb+!buZ}se+YXI_$aHafBbo-r;$m633UpD6w0K4*kCe&p+pVEf`D!) zx&ycxh$uy25K!!agqDD^QkG(20&xwBiGr`L>$({NN)a8!T`{aWDa>=HB=h^8`%D7v z`~E+FKA$k>+;iJ=%em*Cd+xcEa{SzoAN z2gA~YK;OymFNqytSjr3-CX?h6mMn;6Yf(=)#STnM@uu*UR)kTyBw%vv#GaIKxZ837 zdBmeUH9U2`DULzE+f&p+Vt=)e-A66Vz~8_7sfAdBT1dg)tq6Y-VOM&q1=>9~v%wmj z`=Ye}J+kVlV7s%)Hb~5tZpOPE^)hah zsSeSZgGeD6D--fSxs|xGwcJNF@Fr1TIaooS@fcB&D^A-2?XWW)V^=; zxMVcaKKwhj)0K_8_c4Ojl#l+9b6YG+Y<^R2r*r`4hm+x_scQ*IaWO5TSm+;&TD^)| zO**PK&9l6GB^I(WxSk0*LfE_Lc4H*q9+BD$J(+O`-glJClrHIUy6i0{|B|r$fF3(P zT3&v%yj+x52Hg*&T%3v5?Ntc-_A3O~FAXMt$LgxIyNpA{DwB!){HYJYjvk&L!%}L< zHmubnY_m9op_zEAE`ADmgbYi%&~1=Ig-X>m*L=L;QK^ll`>~d&fuL*HZywt9Q5lWU z-KG|koHEcU4AFX%i&ITvNS#YkdP0{ts?L7RBMiZ+6bq9?k!6J<88z~TMj8o-A*ygTeO?`LnST^MOjQwaLx6(-Dd>{CKq zpX@ZzPRq75B>fATPov`vQwqM~I}STJd>;FfH_+2L2yX`L1Wc*_5wRiuJ|5>&>;a9A zwH*EkXD8j^?<4+Nla7~G$6=gzFD*stw}I`5=6V2dOcZ{Dm%M}Lw3COI@zh&+_*NcX zfp9uQp&Grw^;UBDdLG`3$6p;GJ%=2=9BcN6;BN{O?SQ@WLegW1xiy-@LV{UCfzpIk zD=#F?`|@tuccA4&YjnPg`dO|~Gs15%$)o2V zfM1J#<)?s0@%S`vLQ(_t)bfs%}EnC%R}nki>pFxc;H8#R^&h zuG?S8^?nWYCT)i}WG7~K*WEO`Bf-6xO#+`yfgsI31&7;%G%Hmc{v}8=QN!V%f;9Vd z9R5D2!0d}v??k<51m&YnL*)^KHXjBoucz0B^kCE<1A*<0wyuHt27SGn_jOVi&C|Uc zjw6bl@?MSaR{_IGVzjS1v0{xe$t^4KJz)2&^mS5?x_AyPwA(`(c^+TxH1<#~A^qBD z4Zh~5-eY+RPp1ZPC&JRB?K6?rL!RY@loEB% z;IVFj9f8pio&QMD%@;=S+REXXJkB7*mq(%T1X)gy)W4(AEz;{W+KD?&K0cdT0b>o|@Kqj8V}z_`Lek|A$i@&eV5-XT+z~omBHiy} zicV=oh%}|Ix#)bz$j^tMtG0+0s!C`$Zx!=hIYDUU#DiVZeK-TNLQ^XqR6##AmF#z+ zIeG@?2MfqI23m1CAgLJ30X?Tu6EbYb$XOf}g^=+#UV|)=gV9yez!G zCwx)(&pq&hu$9M9pvNB!KZZGr@8`VtKGGdbCmqaVpiK?S=Lfd7uM5F-poRS!vU%A& z#KCumq*bUJe0}h<0@5)FOKBdIh3T|WXwZG66k<*Uzts&x}*qg!U4DNpLJoDJ=fMsqxjO_v}bKneC16bz3Mx5X8yMY5Q#TXolHMMLW z^~qvjd9=cEjK-(TkBI|60BkS3dgi0l`{*1Wd_v~HQ$yD|@D!qeAIX#=V8l;kj&vJx z=;pwqqm}?NpB)*pfh))yI4hb)rkF#<9!h_tUmLAK@6cHAa(NZehlo$fWyJC_$oCug zKb6r_I^I`BESb|v!Rws16?5h~r){AVYqYVz@cewMI@lS=&3(nC-|S85t1fHOD227k`5z6Y&>LP5`6!G zv)&x+eK@{yF!r0em|m47@DQZOx5OX(2P>%1HX#1xKtHb86B-PaT%R|QpE(If*xUCUVMjg@jFazr_P(ul zRg-8<#OqXiZ+TVJPncrso5%EJ5q^U%ksdh3tR;RoJGWCM;$5xMICo z9f}F$Lo>Gr>ufxHHseLc0F4F0L(;AAshEd`BopE+GtEHjMv_BPUtl?oCt+b4l2QRL;W85K01|*LjqVQ6A`>zH>$iWb z6sj7O!lXvrhrr*DA1Q?c2=n6)zWrd=4IRFPX2P$i-_EFXcm?nvlh^D*U;F?#Lzct9 z11|y_jI#BhoaM0Ghr)d9|9}qxO$XYi9KKF#0G@%m*_L94mWOZ>j}_5uvt*!TH*TXE z9c#=v8$;4zgquuj%!>iT;sKx5&4mjc5fVnD+m)FLvRqj#@P+J=Y-H zt;v=~T?Ommmy5nkKrU9)dM{wAK{jCeN-A}5^vkH!fq-iePNfzJP=9pfeJ1f507psW%1!{uOW@U?bowfL8-H1O5T<(|}U} ze*^d!8$4u;DJXpva>2Ii7|TF-6T;UbPA1^b0gnZo4fqt`;edw${t$3F;1Ph|1DpZa z3b+>VAi#Nm-vs;=;AFu2LsTY}9h7#5RFKTz!yKBsyI~nz#m1&}O1jQt?6x%WH%WF- zKYpmMdjb2AAYKHsVZDC=^I~&tP{O4mq}KTlyJOdf%q$N31fiZ|1J1N#tlNF1ed z%rhO@7?gekf1hD$0n`HMZd3O2LFr$B?lUa{I52iy1dmYepQwyMKKzEt4Uk*xJ0F{^)0jdCWr|A%&7XjU2Y5_!Y z&lFSkD?!-w8y&@_MSz|HG|6-b(35~Bn_2)Z1vJ5w{c2G96Cj6a5g;cZgXs{U`G9US zwE%h$(6gpGW-|t*nSkZlP5neC@!e})P^#=)iWa9em}oD77LjVvt7OSfFW2GRD|_5&S0^LFPLgJinuBI z7TzZd!eU?O=$cQxj5TRqQOCxjAkO0wS`}Jhi1P5&IY!4ojHeng2wxPcC~h_P13tD> z&GA>kr)V7tN~2KQ3KPi#H!;PypftR5V9#tB+DWse)JNw!1NjIW*l9t?eF!l+Ugcvu zt+T|pK(_$5u_I$H;+;oX#@K|Od^;fD;6ADS?JV8df0gIZ8Q#o)Uk_B`E*_2AYMf7e zHmMQ*8%kQvO-l1c54FSYBpJdY09y_aFq^8B%UgIv$p1%$xvbOrAVr_~}3)`oBIC z^4`9eL}AY>qQL47nlz4HcM4vU-^t-^9G(bR6-`wbPDQGf zk`bv=kZVvH1AV-_>j+AD&>eJ_H7rcBrCe?XuY+74Bab7)eR&)iPDLr*b?X)W45duu zbt~d^P-C@}`EO8)@LgnzV>e0^r$cA0VyJ%uoXiS{HxSmG00#^Ex+eIV~rxrtXO^8YR|8=IZ=4`;d0YArMmDz(*BFB&i zbWX-#R=>L)i>Zq zLUB;=kvE}4<>z>rZu|JSpw73({(0-bSZy#?DrqT=6Gnc~@Q3k#zpB;h+}m(_7&n6S zwxY&X7o_|}orj(9cvh*X5D!;gfnD065N<6gYex6WDWxyCv-4xRi)6)lZ*61iK;>(; z*i6Nx*fFX?g}1RaR#Y;(^be5`V zzxt}RZo?7yNjo$EBX2a9;~2q?SLE1@6?h*lKJ4$^n%FEAh53JlxN4KjssPK4DV}K4EthY+-*Z zptnw5@+P#d79-MEkpYJW9>$6NLF|gUZ2pcUBi=vxqD$Z5f<>mSZ53=E_ZL#w$6bx; z#)L@bv+&wOZpj7uUv~nfHMXw933&g5+u=jT0BgXo^e(Fk7?x03pQb+tI}WYGpTM9hy1<|7VEa)Qp=THIB)h;jUtq+`q!YW31yfq#6jTf6LsPye)>) zY)-0pXvb7l{>&V%%Ycn)Kw8lSKNz(LpE;rLTeTfAMW!O?jGf= z?fZPK+pfIye7_eAMNBp9u)Q4?im;7^t!!_Lp;A2D2f7QglkIb`ZzU`eBPMR2$oC`N z@|al>67wJ2Xed_TK9gyx&Ho&3_XJ?QNiUN6=Hm3T^WBiIZA84$;fHUzXOjZ3-h2x? zd%O?XVVE0`Mu1~wLuauTluW>RfY$>y1Gf1$B*`y<2Bf|p>ahmNr(dw)hi1#xmOEGO z@5chf9SMg7vot9E5x3jA@0I1w1*gQ0p5A(UBN8#s;xV%kdUrqoPqFzYi2>ysm`C+Np6gNWYsbi0hGT=4)I(QmRS51Od$3FJRD7r(KjJr+=oua8O@W>F-xRSLV z-I$ekXAR;ra_`3@yoo7=fvCmZzs`7Y7nmi(f8sT?Gy$%nB@Z7T^f=`;EZJV z{G%aXyUp*$h$X2gD1Arwr@)Kp_D70?`(VTDIfFC!F_05{kkU87Ga=s3!~QP|`{rIj zxn=%|et59cSuDb@vr$8uvovnScGRBDeLmN0%q%_Z5)bP#^h1hPxUnE5EUU^Zx;$_Ns&gSQ-!NZ*-o6HHFR&Z=Hr!2el+kW;eb*TI+87 zDXs}1%v~6imf?0mx13P`U3B+)KZ1w%=PN}f;79Vdg0B^BGAF}l#mYxsC($#ju}9A} z1#lDpX4H^Yz<~7END|G-hBEY{9=6X@kfUoU&A_jbg5%gv(FzohK5AG8ub9J3FAkjI z7IS)?U+DgGt12Eobp_kicmY23ax~{Xt)ei7`%fkR8uX{f=ul-1hL=9kH_(!(R0=qS znoB1^0ldjUV@jJ#y2@Cu!b}wU^1no=Z-_$J?g+epo#;;W+fU>{kzT~0QyD*OztynV z9F|*ilsx!4b6sprKJ53(@k&Sj0(kS8ldr`8GxJmNe`)?r@HDbK-^Ets&js`ZpeOP7 zIR2L9(|vKsD&_#ZO>99pX`LvH+BhIR03T8P7Jb5;2&ei|eFD;Sd;xunjNx`FZYy_V z=X+VkrPO_KHABU6*ZgD`PhOiLliE)VO<1$D9_y4J#d59geX9h+c4~fqu&Vjlh z#LGhxq9Id@FgAEduV~0}gnWq*Dl?IX;hitwB^}_WJQs>_f~QG}rg<76#}GoJ(B@A@ z-QEJ`>%sN|lPPo}6p+a3K#rS&xZ8T-5>^q7n}YA6xEp)orh>Y*CoW+tqj6KCahG-_ zqF1P-G*B1!#3gJ&G;Ufn?i}DGq1pVsLA?i9Jg+ZdcL9@Iov?|(8X?8XF>S!8gx<)< zh8`LNJc>noVI)G7Jg+`TO{-YE+2-$qwhEUABqMNZ6!!r)0B`Jxodk@>`cNzo$-fLO%HkNCzQ{jfO^xW`oyG z>oammBwl}R?@k~T*$FO zpiSzGnB#$!bgairF9asn=>uT5plwPzKEPT}CoVS3u3XTE^0eQhlx)y#ZQoCm>HR@B z_0WF+y)UQ#5T*M-PXc`)Pk$NoSWdru16|}HKTe}q0Vx=cnA0e>f2%1VwPR;WP_#Dl z15yj<{JZ?yK))Pb6aC76A@6S}cH6&@_iF5re2Co)I?t``-=Kd158@Q#-#kV@I@Oc< zCs0rD)IUX28<6@~lwQ(t0xk0vPfal8ACUI-r2ZMHU*oBNj;7Wl^%l^3^Do(in!dun zWD~xG>NW}V4fvALygossU)}v(ZP$Q3$#c7g+^81{(29?OKA6Y$gZ@WO_ebe^&>!rf zOQ7G!>Cz4KyQ1`xjs|?oM9>M6^QZJz`-K~_HU)D$A<`ZHM1ziJr zNkfuz}TSRJIPs^PKU5xh1X&xg0twVR8HiO#6 z^#ZoG<|wtLhk6Fo%Tel?DD@(!YF_Uu)cXwfvo?QKw9R*;&HoO1GN*3={S?vL0!Z6E z*5BtLzeGb;76qUOr#L?%M7Gkv{0|xUT(q@4gc`gN((!~yQJd~-Bio7wJl5uKSpPxgbt#-@!TQhZbv9bB4^c1DI@tVl%0_KV zAqmlti1`mlq2XB84fIZE6>R=2oC^}&&#`-eJqYZ#;1-rSn&>46X?D*=*uUruKYB;( zXi`ABL@C@rx%C#Ygs`lC2|;E_T@L?6ma`+hAn_Bw?Mgt{i`ot_{_~ZdT4PHJo7qJ&TDP0 zA(sVKj7mvIRH;{`xx?m2Dt*)8yE_ddn3oNSF%UaYOg?w#V|EysMKRk39~l=W56Lf<|T zUsP(TwC7%o)|$7?6BcFu#aiT>Qfa69WKuaOww?%!&6AZ%F*YLG(V%knqbm8Yo= z)%MtC`ZB>ptxhd2x9*m3cWcQljFj`4G^eYv_F21pH{(7N(j#no7x@r+);_RFPB{zr zWl?%hzZ?l5UOvu@c?gZ@fV3ayUAXNRq7<|rR`~26lyNN$-O9vWF8Dj5cTnjJ%nToE zBqs0aO_9W%0WB8v3~KFs<0@77-nh&%$L8J4UI@Siv4Gi|0 zz&e1f0JfTAVPN}!JqauqI+lEXx`uW-ZmrXpHyla9NvP~MFCe|ll$>Xe1($n{on?2Y z(X2N`s#sF0(vptX1?g6U!i$~KCcLbSU4JZmaw#{#k_9_f(L_2tD|CjX_43)VXgUT> z3HAC?tYz!j=LK{EYlq*6$EPu9EC?G9Y#Fej9CL6V7ECg7th*P}Io92a$sFtM#W;?2 z_o9kp-M!d}bL3;JyBGZ&>+Z$hIM&^ZS2)()i{EpsyB9BTth*PRIo92aUvR9u7eB!X z{=WxfHt=5j5VR^jCgb1}qYC3Y67|MGW1GQ~;IW>ueSqiFJ+}YMvF<*u=2&+hS8}Yo zk6+@LA7g`N!3K_XkCfG@O^|AXQAG2NNy}i1s;|q0%}UH<27k)9-)zQveGBJHxS1i00=$_7%rEfZYu29LIhM(fr)UE^zGMz-|Nf4adF% zwglL>96N{8i?>m_mt!8#%0c^qW1je;QICF-lZp2X$)Lyp?Vf+`xVB%KNKnB;;sn_$;;nG-JOv5A|h$u4vHJ{Fd1 z#5vqTP>I9IH-v-IkK|Lagl@5II0Ahu-U(64ci0pdfn~yG`6ipf_Z$389WJDicLARD z_HyVfPN_?6bZQ-uUhaY~6i8(uoC%TTG@bl{(?iPIGWUOAHOr(Ak?xj4@_EK!E1)>o z*zQWF`2C>k6JVdEKrf5XFn$FdOdd~{r5t`m zxzIpDD@z{ApnXD)L8%|glWR=20=BlXXvwF75 zpmZJ@a5={Wo?{z4zsWhyMBZcPQp_2_lkinT`B&q_Ba)17L;Wcy(nv6P&Y_#?kz@+n zkMB6xnS~bUlCsg0=p8$S)7adFRE7AKjrf+ysQnD!ii5DZK&wz2PDfdpC^eGIM;=<3 zN$U{jezg5%q!D+7q`6%zryoeB@o{RIdZO&Z)K|=5s(zg}a;kd+|C>|orZ(V`*F@C!I;XP1 z;*)0Xub8>dh%|2Y@m(>^(mcd`6WqqZTRI2Wbxt%G*mX`cfO-M*x#NcUycYQoHU-t;1V@=#bX zk=G^Yz)@OQ@*zgIZv$#SvO4IJcJpz``9GgULCk~zyh_aqYT(O+Qhy!BoPeITvHV@M zd-sgU$2$LGXgHq{DKi@Z5kkB1ArNEJvXe!|qZjqFHtmdgTq8xrjLl zzJhXThZ^;X!=x=pkrxf2JwrbQg8TF5+V@@SPMsT}`|~dC*Pb}6J|t@%K&_}gZ;<5E zwv(?VR2L>ae|$CUtjULl%JKY>L`MaE2hN;aa|_#6Pv3!+!;2XtWKM1BUfp&Uo??$L zVbUYWa~HG0^VyS;Oq6po;-&=fqRtw%Lv>!hEmb`&kISQ9%_V(3_O{)&_gpS14rW^H zxbdAS&|7;q<2(P^m1a?HRaXibMvMaGL2adKi)JgVcj4D@JWe#l$}H~Lm2PXpwY;<^ zBA4?v&NFwgZXXrCl7n|{gI#i>Bh$IinQ&NnGW&UbMqiiykn-bx8_%*>A;l%&Rz*rh z%z-oQHLbL|{{#sj%wHUYbxD9$Y219`t#x6p&975PxUWgvQs!`bu`2yXKF@Beo+e4_ zx&*XLH394Mp7TA+a$P&{uLz5?b$wWw310Y!ikY zaMU{{6l<%0o-;drS`jP(<7O>)heECP7SYoC?F^>4{kD=4pFW=YhqQm_=SI9+;ra(l zZB%SyuxuJ#tliOq)KiLPFRu-SLPafcIhR1ywHlT1l^IP(Z@s+5?ma^3726b}nB)k( z*P5I-*3sZ8aoj_%$;2GT+)|ouN89e{BwIXc-)V(-d)F>u{|_I)Pm)i(bM35MrbyEI zPJIX7HiQRT?h_BOC23`+eyGquyL7O zgZ5v6`N5>IkQW^A(M9K&ls1k3uEE`rHvzTQcJbTOvVXBM=sx1>Wq--wUB;J>Y-SIq zX*b_hTrx!%s>ss8dy8n%Y=&>b%Hqj&c)b-n@oll&;8xn_&)?+Y&+g6#;P~}*d=7kN z9>(czjPu<=>9t_&j<_1Ups_@GO(=gpwkGz``uf(J5@XM+tL^phxa)A+Rp*Y{s~Ut1 zF#~>yGW@j}^#@zyV`v;#8EUae!)1of$Se9sc&UnfLBTT=Y0C zxb-`BY`xZE%&?fK#yRjt-OYQ?v1~_L4YdevgJAzm60QUpiFVD9Zn2i&1_`tu(|Gs@ z?3JTbPnSl2e#&FmiT5F2skU!`&#c`-L7-Nd((0_soQv!#6f{%b+9Qq;nhAELl zmx4P?dJdfnZZ#!ws5uCKXRjB@)_p>51mabCYKdyPbx_>y4G^rQ>sxi_TO|< zl;HR-XY{VKBx!In{f%h2fN*LxiWBUVeRmMt(Meu5Uozfr6-3z8 z{Vhh^w2ST3YdgI8LdNv?nmD0CvB~K8wB0sMxfLf_UDPXNcR@QBSw?sqYyJhCsYg8r zVoxhUi+zdd8_8eRJck&HX(iuD@Jt9lvSTsQsOLz!&d0Zq7F)($9Ixxa>Eur+m!vl- z?`Z4JK+r&5OS1kzOR}Wu%t11=FynlAy)D zzTUZf-RoU^@cMeU)1n_LuPX_yixik^+Z06OT?=o-)uYn8C=1Y6{y@Mj{gMZ*(X zAMJ_#WaLEPQR9igBi89fO1z%fr!EUay->gFv<0!x)t!c$@QZ3MgEek|5dk-#y1=2u4A7{akRR6t3Bd>;GI4-lY_B= z+2bw2*!KQ-g(~&-zK0>VVWt`mr5}cqQt2c3KUx6)M^2R8Y)GjlFYzg^h@=hDY$skA z;IbV3K8rq+y%5qkk))5qvNtW4U7j(=!7H;ctM`KAt~JF~OVV&~FQ+LUP$r-lQvx6h zAcd(Hpn-t)nGyk|1A4=x2Sm3mcbJj@k>BI3rer{|fMTnu)g@^NU>#tRWd;Re&?Ce* zqf^}5S?|%JcRNcRjoTZh9g|v!Ft)n(!<}FQV%~J-X0TBT<#cs#J*`}i^V;uZb z#RxIA35T#EmD9@db@&7;z*xz%_P^zH-}eHB-YGa)?Db8rgBpu6q)jfqvQ`qP!TJL*-{uxF`wf&2Rf++=4vK;g> z{d*0cw+gYatmrIhc_EgxqD#!1CulE;I9)w-ZRa9m&Y@OCY`Z6~R)9A=`1`A!Rr`eS zSV#ZWy+Vpd=?&-Uc189hm-t@zuEgLgzFelMz$>Fqy?NF9)b|r+do=KmrI;sV*5XC0 zTD)jAt5$bG$QCa>IBqkKX-6ZIJ7YLB;xTbCkM6rd9-{Os4dTd74~Jc9rLZJ<>7Zof4m*6i3pCq8=;p zsYTIqi$mmZ?gXSmSRVvP#2-a^(QJcHvT|73rQD=d>0i>{PTv}MG*$LxEBgK;pFF}E9iD?7eyO!< z3!5^kpW6lmk^KJ09^n$Qkfr~nIJ1+Z`vh25Tvqk#(@2bAD)>6pD2hGbfQ3b z1w3QpJi$O~dOL6VAkHaB125NEl70c#6meqv7yOPxzf5N8jB!J*ugJt%FG7z%(yt_? z;Re>%?Poe@&c7I;(6v|zBq@f6f5yYtM80NoMy(xR(y}n-MyB=if4{8GfK)%@EQ~3~Bk-vH;$dp_$hu#WHbhqvvZ@I*PRZNF5W9W`U+S2wPLg z8Db3XRN;ifA5mXj2)*$A=*y)+IXC%>FcQGep9vt}GFhKbudb%y^eYiwHL0!Wr8Kl6 zUJT20Nz$L-TY$?sph)mKfG?M&3%>*SgD4yNb@3Lo zoBt-!FO_wU_nRIfox<1cU$%FL&g!(f#oIePN*?}kyXd7@-PGbv9jL9?k;r)z;pUI} zY!$1|FT(6vk6(FA?n^?uOqZlTV~^D(dC)S%Y30`lBxx(FXOr$J@w=A(B2rEnqtE_f%pI3mKnb?u_4hWI`&ur`mMT%;<9JX*7sv zsl{xkw@XrDeuShj{>Qsn5u>HJOy#!@=E-vXvT1(l*9cZnzQR)dREKO9s+kVFgi_F`UkOQoa79;}4*L>np~}FX#afgVn@iYBz|^1>aoPr8q_OJ7X{!StrjJ$)H!Mrj!HeQmNf4Wsv z;C{CiH$%{Gq8Tv-&~9<*M8|Br*Sc@-zdFRWhLE<@iZGYdj9*HS@yk~8CF$GN>F_* zC8+Ay0h{tG*0*YpvYn}WYoD);_aqeUVLR_etc*x@N)y5dZ>}}Bs8n%YQ;S-Cou-b` zQYrp;5ihwCcd2Aq7#*b3JK2C6FYtH!qcz?WyL?)0QtOJu*o&H5rq}Lair#yeDuYS? zJaIIj7#&wyHj!S>*4Cv!`x@U+5h%#72#m@XD`WGO7x3Z_-a@$$>2*TFmr$S6*eC7( zm$jDqCRSB|w8p+=G`i?*0(#M4AjbUfUTen5p*$z{U~G}({}f{03_dXqqc9gdgyu8- z8aox>Spp<9lK7!{3}2r;uneiE@g#Wl_`W_E&z;cI42X{B72LX@i=Pm6No}-ZE+vja zyD2|jtB9VS`qiRe`VhACGOcilU-~O->0@a{YD>%YOGof(OoXSjwG9P+0PE}STc~Gg z7A=mxv)+Z)mcN{4MBlP7-q)cP_=MN$EYiqta0H~e;M`0q!1slvPw@5h$})NHr`$4N zg+_U+kheTbZpAEdIj^*jb<_WI-GVdCH?>A^rutsrMgKp};i4Ua^Ec^(_XOv!Qqu{+ znc~~{I{iOjm(p4D*!CB7u9~M)@anMORG89y$9KxV2k@Kb8(w2`ek-Nd+nhsv_rFFV zr+99keMnxaUv%EFP?@t9{(ny6>|*Qle{@c3vN(ktgCp*O&Z~4LIc!eBjQ5x`Z)sA& zce~Fp>deXXqxQUWw()rBxK*b(pMKb>%YDNz*Ff*p_wvMe^-S4#X3m#$;xUT%+Xr~W ze6nAC-`;jH*(>IxdFDI)eUFS!{I7VL8{&yZNb^?P1nInB%vqJ(6 zY$dPNyPZPjJ09Opv_sz08n0F34UBllCivMtEA0)@3EP~enAUhmOdjbN+v9wAt|DiI zM>+Do^W_^~w@>pNXw~cT2W-V@1~eJo*EcQ~bXM1dNzJ;OzDpPIGNX5_JeJ_uu_`7;l@;T;_%v?FdFC$?^XJdI>=g4amzJHFzp$u&&&&Ds z3ZG7B>b^U7f@Wr(ubf-&K5Ttxp=eC;9(ID$=48Q^LE*{s{p$jqqkq?BMUSjUkK`;A z^K<4Zyu+OkdpwpEN_@w5d!lF0%SEt6e%N|mt2!g+8vl*49$yQ;(R)z-WhY+3<~6}x zJ)GgvS+Z)H#;I~#S#0)wdEqPeNZwAn=&`IUa{s*O%3|e|=N0m6vu59tYP^3s?pdUv z_>|7-h_q+;&M;N(#TS+JhWB%p;|vOE+ue(oU#?&5Y_5mD{sIgBcjhj3*Q}WBCa)3j zsp*^jZK)ffqF@^1`|eu}&R9j07yguByWt!6&Eb`CNc|#KK+3tuy%=pFpr@7al%6v$ z&-XvyP@k09@_fU0Sys?GOc-9BYAEA8R5eZI$XTv&Dsp~XG|H3j?6+FT$!*G6te{ud zZ~uxlsm;EpF8t+cg;AX;o`27-K7V+T(Q$QN1n0B^yjSKC=U5t{S|3HN_w>|S__mD0 zdf)vQtnP!0=nEzbV|=T>rB~S#e6M}ibwW=qn%jS6|9ZR{1s;T(jCeCaPw)6l+8+r@fim8s6*2hJSIi|HNrU`HO zjHyq?E0pV%F|DzRA~t@QSU~3>f_Jy$Yj!4g`-C5wbDYiW1C7#ob>^+^ek*d^gWXw< z=?<|*>-!JOS$Wz0V|}Jm>8xaJRv~9pQxj_%eQ~3ZV{J-4jJw=-PRA~6xNrN#q?%d% zGn#tij9%n<-L|3fLz9sLOW zVXLr5k4U~qY0;PyG4(1dxGQ3aS;{6=GrjpCdMT`LG+dpPbgsm=vFJrx+?f)e0l#Ye z3N!F~wmY6R8aF1Z7r&3HjfvB0W7PP$F@_@=D={mD$BOTzkB{$_O#gJTK)T~nygB&m z&b6#=xm)cNEZQmG2-8`9>DzXtCpmqFbNfWhlYDhfn+NrW-Ntr&qnKroZ^>qh9?DPt zvN-4pW6p`UY9=eLu2W27X6vl}%BDtxOs6=FNUOM^y_$fhLbE0cWfRGV0a?dKuq#$> z++)`^;U#IT+rI(ZX{YkYZnjr6&W{K^YS$nR$u5`B+B$avxSI(7RuR1JO;k0{L7q!r zG#DLaCzK9-oz5BW=xt7SG-1DLarQR$&bO4(c$SKwLENNr#FgC*&$9`R;<7%-DIV|8 zM{q0Eh5t1X4gOcc>wV0^$u0VYx{fuICb#IaG#zU+lUsUcJX$&i^lQ-1&~Gd54dB(; zj7MEU#)zelE){EHF#?^-Bk+kGJH+MC5|=o53t}FN^ez}~5Jx*ET*IpnC$4m@BN+j; zh$A1gkNMV!3dkk2-k)xdckAjRxXr7w>TsU`UyZqkGJ9g3ZV&l}l#)jXnQ|p^R=SO; z9D2+jl#CfX26LL)fMhf|*R#?H+(8hA#5)pPlbsqz5-gp5i9A&LXQv7LAtL=05iG=Q z1!vhr1$uD|bW!A+;@@3U-6s69F42+chNmygnSq@u^bGoqjx!+Vf)1bGA zz=On0)Fcnk_dFHZ^EOG!PAI>yZcr*6Qtd#hGW51On#$c(%2TOo=)FTK4e}n+{S=Pv zNf(QBPybiCEjOfl=Z18D|F3j&dAc!pVLKHyTiK;_OyXbmA|NA5rZ01cRTcwUuRGQs zL8I@dH+NU@c&Z)rExW?H-^H5&+Dx~qMvnOikEz~4wci+y{awtlzl(X_4Kd53G3hm| zM2BX8FhuPwzwdqc!noB@evdfH=#1brZ-c#~In%*T&`iS(k_Lu%hO{dj1H{2JTts!}CABOJ< znY#Z5>JK3$pZPmGl~L-p8>r181*g7@-GZEU;|soD{i3H!M~jvwR)^m z9eq)4QRgUkCPqbX{-#rtwDS&zlTQgf2Ya+KhhldT^d2qWs^pPUa#s6ZFJxBvCgDo z53GTbkK>*fY#0%muI&qZ*{cdGm3Dof#ct@?~`b-iG7>M^F}KRK2Lv3?30-8WLHX4o0gn?tV; zIHz+Yq0FhNy@LoYkFLEBW_iB>IiXk^AR83C^5s^QXM(d(x!wQEsg@y??f*>WM5^)sAE{=A zb#7R?5cWRv$pH5j`N^5htJ@XpQx(CNXS_rgH zZL{Dv3!ch^DzQpYrL0m_wYBf@-|8$VeY~`i-DX|vKD=Uf{aJk3c9nScyi$EO)4^X^ zwWawwUnA|2R9A!&zL=SScgl2*_IBv44lU-n7WfLzSx~k@X(^rWEJ7XTmx_>$p?#_r z^At@#I4kX{^H!7}!K*$o-qU@_2T5(Hz3n}xX`x{Gsl8Wg*9rQLFJ@|-^PSHfvG`QT zLyMKsif>8uP5lP46*OO#(wn_zXO@F*b(%|s3Rr4YC@WMI35eI$eycwpGW%`T%lMY& z8@?qK-;(C@eS6hub)1K`0XnmK3+hSr?d7F*k-roc*bUZ&qAArk^PF{|62Et!qwm44 zx0G6-$VqbC7c*6sCTOQMj`_T$FG>we@C9%Ju<}V5sY*lLM$1wBiZ?-| zT}8fc_jh9T3~HAeX!M#cJFD&LbJP~fP@iqb?W$(EjaEi<-s63#ea)l5y+g(lzmZ;kFFPO^YLC#BV|a&E`DfqV;;VXyZ_!~MU*CpYx{ z9exS+>k8*AH#9t!j|`gvD!q`UyC~*Y+9i_9`Dmpb3H=E^Tlvve*BYfq@U0OFe4lTR z+z_hsG}aEvRGc?vs+;Z^)2I_6zyEj2IM2yiV~(zAP|n7Ndv3j`6Z1b-D9_I9FUK@s zMiB2H$xzi{D;KV&U>+JX%j&eA!nU%dh5nUBAxGDMnR6m0Q+a-O>wPM5SpK>D@KW*2 zOkG2aQSj=FiVpAKW7k~c;+u|L6UN0g)n2oWi^c!0k$9J{qh+aJR(T7|3hyJ(xwe?& z?-Z`ugkgq*vna-*vL3-(ZZhYE&+jkc69_Fq zuPv%PpTLeFSmrDm;H8!sgf_tUcL*w_M>Ik6mly9HlqsJ3ADzOxyY(K8Unh<(@QpZ^ zi#JofW=ntYPFSzK5)n{)+W(gEU2xe6e3??ri9bI-Gq!0#rmpFsOik0nnX0BinW}Sw zPm5ck^sUfQ6vIMMD4XcRey6*4;Gqn!%6<#2D|z+OU>2#oOVdvq1kHi=zqgYZ9C`A?}ZA{yf` zhkSLrpm8U!^-gfzKYFH@tqb4?dZJs{I zkJ^xrvX{H$m1+QLA~bl}bAo-ja(S|%+R(ThBW6ZTEVO|!N!m#bvvoF~OR%*l_1&Yf zC1P1VZ@FnjQH#QSc{z>!q88C&^9f57KI~bog)M@OQrbFP`V0J55N69bRuFyNx{dL; z9j8<(a*~>qIm4SEO*HA2t1UFD)Ly^zN~dMH(x+86&Or{)fy6GqygX)w0_7xYW;UQU zWmMiBfYz2#jC2i^B?zDa-s`a|%{1#A>5hL&Yd#c&q$woH zfPXdiL96$6q=CkqI6=0tT<_? zWJ=dAR`9;fw2(8V>6-9MtuXZA;rZuO7?D{Rk+Xbb-XAnv zJa<*6^%{q3o9ZxTCpGMAy-Rr!Z_0tkT4qe>{f$@y{b9odpR2s6!<9e5x3>I!Sfhwd zMID0D;1KW$r{6AguiHu#ULIjHvtIQnX%0x+BZ$#2iR=>wT_7bCWnS#`7Jk+Kq7$-!~B7 z_yJ1SU+C>sj7%Ut8UF#SwG*2@XjLV~dsy%o^6n#O`|?bS@KzNq`qk%^b*uI>ee(-Z~muL)wx6)cZNdHGZXWD z;a!xbIs#6Te|bH^o}+O-rcTfO=%-m#lm7`TcCsWO$p{*d6DAm#WM&D-0jIODLpj}k zy4KTv*I#L*ymX{*@h*0^EB!95=~H0`xPza2sT%4OS-ycd@Ck75<`2ai9?8 zUW_OX(60SdXG)D=Caa`fY?4)Rpr$Wzxtl?`HzJtFU^Z^Cr#4t{_C))$cz!w>k9z$0 z+jGKWzTV(wf}k!IjPRv6@&*2eLSt=Cro0-xi7{2dKDMS{W$xQxGgPn~fmRJ)ozhXk znrs#9ucZmz0qI*<70!XS+11S>SE}z!V?(FD46Th=@MG;U`)|#}X?-V-ATL%o5a~X$ zra4X;2AA|*DQ3|-w^fbzF|(lcRIThd=_iXUOZdCD19W}5A+Sp+E%UNas~YVP|Yj7Ki4Y^ z{{v!bJXOq=yUwm?mMK+%W&)X_JMV}b2CofZ!=*O z=ADAyz*Bf%qKY*d71`SxX7pdr8m(dmwcH2B*{iDUgPN&rF4tGFYt{=|!x_90kb6;^ ziu3J{tX1r^@iO>om34Yh*?wLdgERNkToLtb7SKB4Db!K$K8*8$Q`Ta)VD4L5b^^1d zX9o%C45x=*SgmzpPG3(2yJl4Ql0<#ht)3?KfgUHewgs4Be*Ljf>oqZyR)`BgQxDpQ zc}NC#A-2I`J)y`M>^XuuVMeM30g5%Xxsh@z<*?A;#=E_kd+<8W1^BXA zBCZ2rcnMab`m3GbPc<%ty zl%m?JMT5-eHQoxuaCam@k9t;X`*z>lz5JZ#cq6gFx8 zZs0i8d#LCk=-bg&6Q&|BTddfNj!cv2^!St+_LzEqJNP zYBT9F!+`S!6u!^bd%&#i^ZETA-@m@%d)}9G-sk-~=e*82ulsq~mhNU#b#5*-+|8s; z@Fbg1its*umkJs$z93|+;c#9m@M~&q39S@iglGpgg>!Q$F&-t-9z>p6+wfNGF1+Tj z^ec>Ywv{y^PDv_8GNM_~8#OKFcg&cBt&VCbSzuFh+nc1}m}6=%%J$oWxyd?|MkVW0a}|c2l91~}9(GCvuA2PO;Itnct%%(zrDD!^g32K} ziD(JI%H9cX&brl5BMF#;Qq03rb?qpH-HuhV8eW7>)ISgWKDF-*^E6l18rH~WWUUNA z?2sYOA3HbeNME4)zAV1(+s1`i`FANh&Td?z&xhp^o_GDu=9CuC|FyiQE(`p-Z@yDn zWHG<9!!{W<8?dFrv-^!s=>bd8OjAtM2qqe{Fb$9daqfHC5mT7q}cY3sGQPvvm842ch%_pQ8^G`@QmgU~a z)HBkI$cVPwF>D{R=!}#T`8viXt}~kYIy(pR8Sn9~aJWk?y^K#Ahi8%Q(!W^?40MGz zSWl_Bm-SCaN>1eI(pKvdq~t_qpnZM9pW`{7TFnYats8CG9V+FBUUg8>ahlyBePch? zsJ4!~!Z4Xxqf*PHZy46SFyVY7dY8*-SvtBx@|ju8JZgTARnc*YtC7CZ@07l`GgnxS z=Cwb?e%sg)S0R0GMxD${5(sBb;EJq;AZd{AzQ9}pRsY4x>UPQ^WuDId=XYoW}8U;^e^YkE6mKDk|uH#*7cZ{fyROHmgeU{ zhIj2^tYVPc<+z;d+v??o{Rp@y{W%*Z}fL=n=P9eEnN$-?#%7K#n<^XQNBaw(&c#sfF{ghpE&@@QJg;%IRKE(?kQM0_P#AnGsd_C9a3`gS-+yYOBc$tB*+RK10r7~5dY-2MN-G6zEXf%aa z(OvZzG|JsCJVxu>M1EIaZ+DhUrcd-sH}8OV;w_s$EoHpicwjmHYNapDSuVV_{zYgF zh}TGm#Qu@%8IJ4L49p4N8am=L>?lu8&vOuU2xm$CK-69%5KsoRMwKJ$sH)}#H^Hy`73vD{+y4m!@kpNE_yu@8iRY1Cq{iKnh<+^R=RT=O!9Sm5(dBf3s21T~{*4Z3f1EhTSQ^ zp|Sn&SHwE7z7Epf>b^jr&Nl7h8AMWIGlsiqe2tA<>R47#Q&<%TS@CI-B!`<$!QxeJ zd5nupOStKF@E)gv)z>Ni1mtHe#9NFtM!3&N=E!9Q^e%Bn$re~GcrxL^Ol6c%88Y98 zc+Zd(%tBm5@C_N$WcYU6fbZ8ofiLYGeK7}Ld_ex9aN~<+`HN$3`eMT17ei40;-)Vq z!#13tn1cO*2IP8#{RkSW8F(Tb6D$u!zA!_$`rtol4p4~GUDe>1xHJ}X z7DfPi>X?~HIw2j!hlK9dL@IQ0mN1bay z+qas%)jhlgbAoU>t{PZUXB&@ML1U?g(e(c2YU!Guy#rp{=jMPSs+RinPU)I?FJ@(U zb)O5>iJoXdV_i41cijB+x_Kbz!YI~&hx3{v({7Q=jixfqO62bc1q_-3?>VJDoO=b7 zKUl`n1hke3B@0fZ%kgJW4wXf6uVB^y{I1pJEC;waA-+HXPp@OX<4zV)Ce++2;BX!! z){O5h@Z|5BKb1;$$W%+w4|Gk|74^(aX% zXUh@Qz}5-CzXXzj10yD2HJD&onlQ}0+%elRtKhVhd<^((e6J&%tD<=xlsCbjoxR!p zYBQu6k%Yf{Z4vG7cc{YozVN``aAx}wGT!e{YMT0_KvTE#p-SlNkk7b2t1zq9wxFHX z{8tRorL^Yfg4Wt6sRdf~NuGllR~X|y-x!|8x<{nNdUp173b~MK)Y+oJ2c87R=`f#Z zU}qgB%jrHwEH%Ob$Uq0}bN_vfWI)BPostLqP)y56QjLgaGQAol1gMaITY(ZWJNgu?dzUY4bD;f`M3UMB4 zSXzt}XE-Lcf4ODlTWsRzk1PBFq^KIxKLcZe$$&1|Ss|rh{?E$&FKPJv1K=j#Pdotr zQHS3L%`wO^Bez1zMh?+_0DNABWY1ms$jXO*_sH)a{_>G8A3h;DbCVvCDQc39g1$m; zS%&!|IPQ=FeZ2&94deS##);y4hv-td$c7+Q6g_f_|G2RY!xgLDN=Y=7`L zVk22CF0tHpFJ`L*BUfJsJFU=cID{1fu!68>IwBMGK33g#)%PsqK(9Jqvkh;@y4gy2 zusMDX$$*xp#;N+ashM%uBjqaQ^DgK8RMwINt$T%IzGFc_C1S>ojhr6015stih;0%B ziX+At?@;!sdWnL;YSNeCn&=|iaQIHbZ~JTMT=sgha~(%GFW0UizBELm>t^qhBG6v% zq7=f7QJy&B9o!G~Rs}R^dKp9h221Q-0d(SzMqmX-U&T+uqvytS$Vs z4qV}*Xqy=pzT-IGWUFYQw+LpU{Mc#d8+B>Qwh-2_ptT@fzlq)=x!=3yarYcI#Fr|> zMN*>uYs_*4g95syXRz1$BC$i(mc}LDErf=w{#Dk_3 zc1ydMy<)SAIC=U?6u#2Y;}r8`%Jb%)@%C6je~*Cov+p$RJ6fE}-o{R)FTG?tbDlUE z8rM`G-3ygs*glmw3U+#E0gUC$ZYD9U=%`;Gk&M|=ubJTW8)iMZlz|*hiq;ElrX0N# zeT?bIVpJU$U@1PLI^3rYpVb?FEy2e|B(zNLa;|%M!SoVUhljB~N%E3h@bvFPhW7H( z>0J!cURla!aIUnX^Nm^A?(=J#A)|)RO4E~x*yAeCNw&*;djNO0@cVJcrm5Q#E8(xP z1@@;o&@cpsb%(gI7eQ0b#i2hF(gUesJuuJLuVIpEz1+l;Em@%PnA-Hx*+h|B_lhxS zvnSn~iHGPp0iB-O^StCfeBRH7$<$&P(Pc~+_5EAY1JE%q1{bvzC2Dn)qR~-Gv$Px1 zP;h$_7rWVH?gH^g3*B$})e&)`4reZcy9h62M(L%LSU2IhLLgphgqxiZ4StG?&|lzz z)pQl+Ss=pyJ57x{HbQ~B`+ytl*jzwv6r&XV*c%v{N=~@;q>2AL0=_ z@|vup8kAx9=8Y6zo?VZb77D(ENs6+D|xZ74!8tbepN`v@S`7}F?kSO=$^xam32J{SoN*q^XNr+gZG2t4g; z`w^L4hgdqv#eld$SyUkoXYeKyQtQ5ufXO(7Y zP%Dq1-p!^?zzP5>ot_gWHhr8Y?X5AeFi$pTO#f7!0B=i-b<^ht(dT@;T>kRRE~iCZ zr-60o-zB@e8X%9eKloa&0#;u1bpt`%snWqbOZ^Rdffqb1#H==1BpGhA&1lzM#qF+@eW!cGr;d7D&;HhrUk z`UGtfwjCHwI_-W$W}`OQ4oeYg6O#7%*_ATy z;4^Sd9j7Byke9#vgRhBfc}}{AI_L<PWLiQ0xgoB!U=EuSjX6Q(I~(-wWynSt-)n>NrB`M7(rj@d$)%j+vHWYS ztRV^0%ig`&R$rZyAk=t%(M(hpZ0s_KqZ$bQcHs4noCv-($@Q0xnGx)1XcD~RfNNIJ z;*=xLasH|3W@h3hH{(rm9n9viTK8jz21u98d9n3*XDZIK?3ah4>n$xanf@IDN@9WH?eck?gd~rzjG_1{tSZAcoV>7lHOugF9DoC4G z8%Y)w9{=T(}-#dNu9_SwIBPH?solx2Q6rMqwng~alP8B$lG(( z@Ii-)C(iN*iPO_Ak~u9Nlpu#>PD>KhgEA*b(ghCE08o68EnXYsJwtRaUrYNhS3{DR zNs`1O&{#bbw=mj;83F6mU!=Ihe~}Uz5Gkq;G+-~SH3|={GK|mXWA1L^Aq`&Q7QuVReUj(Sg+BLn)0__#2;;LXZ@ zzr`X(z-w%LFLUiA_SlTD)7rK$+kf#n*D-%M&yIh|8s?z&d)kaJyV~Qz+?*ko@M-L{ zxC~e=4&e{^N8u}x{Xso;82_n!aMn zym}zGtDj3|MZNoFKTEsT!E1hcM>v}*%F@<(13~splENM}^PtC%V&(~YLULFd3)}H6 zhZR!vW7?f$D+0?9jED#E)Q+#`=YkSTPAAD{5p(M#_dJ?$?P{Mv{g;k^MVLI=7Xiz$ zP}E0FHK1uw0IrzBs@?G1z4r4^h0z)SsQ%LYQ>f&W-x5^M9@f8fQJMj0asbU-K$4pa z=nfM!W`ahx(MfZwJ2+V9U}nTR0?3ZBK7;D*j*lbaJkMQrszb0KI_UMEheWm<1tjbK z0}?sqx5P8eAX+qSo_k~%X?3BS6;wW6RSR43-L@I9u6ofn9lwl!t`a<#KS!y7C$R_f ztDPv9^&}Onaw$5V;TEhlOvPEHYhG{Hc-J{DK}W~=GJ3gAZCsV1*lt>*YfiK4y(tc_ zti993CEG8RQhJo3%9d*9NuJcsrl;By*DQq`gUv`pg$EEC)`L>a;pXv`T#)^Cp95eB<8O8LwzBsiKa*HApFfmFI6;7*LsuMO1 zdfNLIR*-6D{09tLm(^u0P%H?iv^RuW8{fKc%=t#*K`)W!g_$)gs&t!37A)YQZ0UBI z$=K9k9>{xz(`wUMd<8PxwO4GmwO1C{Qk~3r17@p{9?0R0ZgmvsH;pk4Yuq&6_4b)dU;QQe%nlVYb@KYE_XOikVDlr1tH=u@i+l`!IZI=wNw9u2pem=D*QZ+53 zXk{2L%K?P=Qbbw-mq}JQ(_p`YFX*oa4_!~h>JCY|eu-Qo)>dr)tqbj>4^N>wx%Fi> zZ5x%0Jm&eb1;>n*QCW}McV7-?u&R2}OV^jy*}`Exg{V}BL)BC~#2aF-v?8KG$PN!$ zY3%N}2*>?69>`GAqBLS^MMK>! zqM|0Y&ME5aY3A71lY^17*pBg>tE_>!C7OWNGe3%*7WB&RHmhmGuSm7a`d88f#z=DL@r4Q*@LsEuuY(39-lMv&(`U;{2S$)= zL*=2h;t)mj#2O0xNy-!z-LI|-H&seZF6OoA9|d1+rf>XUY2sfK$ma))<;(S*NU%Jj4zkoS^v7i!6%Ui#yrF+rRXv)>Lodxd4`Y7@r8()_p*7CxKHwq(E~gE3wRZbX#J zYr(u8#Z+O^7aq(tn750py@59mQ>^qoixlFY3j**lH@jIJA&<!CzhxcJ$ zz~Q4BKQ@plO3(&MkZnuvAkHXo0N$dT*kmQF#}#}?V;{0UzYSxFtyR}!CyTTZh-}Rs zRP9xmJ_>$@s3)9TJ2A|o@E(zLCQW^uo%g?4NS4+dwpTRog zmd0*f=&J7V&PSw*boQ>X@Dx@~sqXn~9q+}H1#U@S%#4flhRs2|07L?#*m9sMYttOl z#njOk;qAB+CGpK;AqV)Yt>e6kRz29>e)HtB4EjlQI(h?Zx*Hr_ffw-0BpsH-n4ZAY z&i(LicBC&}lIbenl-A6b#=H0@!kW7SVFASyVInN45obJ1Y;cV6?fHa9d?_Ze0oJ+b zZS?gn-%u*`^~q26BfdhpG|bfC=nkw4(zmX3?T3DMg9*EAosCCtbYefK20+pn3_T}I zC`USMdSy8FEnz0!?tXO>lRDKyxUyum(Z{k&@@u8X^ep1_mP?NbX{A|BlorCDrCW4O z@uhvP2H6MuPFU@nm69_OU2)q`!^w5FC{GIf;=_Ia{Dg%kbdouZlWxp|Onl5%3=eB1>!S>ul< z$djiqY12H+t+#ucDzkh7-{h3*V>-KJMANIAxVP|4n}KUtN@!;^)rTq-A}pQrfN?9HJ$%U7 zF6o&uzJFe9!wB7vb_AwHe;?S4$YTm)hOh4&qCnIFV-hW5oGBE4O;P)OpdLND$8iS! zzFR-r+2gfv8N7!yrd~_wXZwjlMq~iSx3TOHBz+ZYHSWZ&io8QkM059beZnMLeGa6= zsb{p17t$f;PP|7Pq}Q^)K+%!KzqozB!y@jN%z4z_alX0da}aC6B8Kk%bwLjf;8Gd! zGpvTbKCid3v(~oqBAX5x!E*@hqDQG`qzjSz3)tJY+um-WQa{~(sPbUTz({Fv7Sw(V8tD{@~{JE-K(1FoxwKviUAt-Z1^>)+miTZg&# z7u*frdjInM4%Br$tx8_Yp~_{7W#MQO)T^)gP^Cc?duG1_I5!p;qNoN&|1)s8>#&Wq z^%=ff5V2tZv9GC3|0=id47q)eI$60iDuqcKcM&ZlWo4T#tSW3*>&}?Pe+GV!9#o4c zSMkq4L)Wvm2se$)Wr#k8K04pvI2Rn>-+(sn2_*VxEGv*=LE7qb+q{P=1;U|)hn$Gl zb)6Z1s4_=P^f}Syw9@WhZiGxd!xy~x=XLuX>0*2#hv-tB*i($kZo5eM`cKS4!N3MT z{rrbCEGG1@aYii zLOuh><#oS2(xt&V``<@t1!fY27>Ts%e*d?4Y^&Wlxy z+N)?YU<5ii=VGCmwJ6fnDcu)o1)^9?2aJ4y3DNXo9mjCJLo(W8TrX^5CS^*<9rGb|lYmMTFW+2`wK`bJpEZl&B6?-=eiIPR-_w`xS?Tx(fX zfi*m9S0%f>z-r9e))?zrhSmK$cww7ii4*Q1-$6aRQ5fT?z{kD`cIy33$EkqZr|6DZ ze*!vdMR&sbBs5aml#~+{ooFITQc9_3zxw< z>6w;+U>y(9vU#X@TL_j_OrC=UW6YVT@!t9ix^#^6wj-N!*bm^$ku%VWD#SX*g0S~pr6?v zoJkSqo^?9{9cqYQSzNA*$VDy2ELYK zWorh469z6yien4J<>E3(Va)i-WasebBX;X|MedYiG|uY}z63lB&U*p%F`Efqk|aNO zS)+$s=ci>hK(=uh@)@~Q25}%({G`;6q#2O$H+%`fE{ui z$F9Th3x#(z`h3S>DW`(*|J6CqaW}6$tLd^YKH7ckA$U*vI7EhIHKCRIth8ZlO;5Bw zCqeBQ)#bcx7&N?2wE-)#1{ShP`5Es%9ym6NIOSbELKJHWgKrZT!6VwC)wj*L7xFF9 z$EmK8{oS~;QUhxgt-jXwJV&{B4t~h^!sJ?MGqe-;c-p0K^L-NEKr+B0cd|)$P~o4; zo(x9yrO~=#u2&20!~*zTo7)ue@QxU6sc+^XQ+-al+Z={HXg7?lg|70do2WE4wbRXE z9;DP?z{YW>6oFOsvb*Ce-66C!`&c8BxTR51tE^Sks%tg1+FEWm|9m_2Eb}owmtlOa z#QvRMsEpziA9Fs%YXX0SFU0JSHtYA=IQa5!l~(AMDta~9sWRhAz8XOk|8H*rtH=T+g=&iL#JO8wg+ENBIJlv=QpL%>?SpTH-FPearngd1hok3| zhsl1Q-qR5V%n!Xi*|!E3X=7RT4+Fue*9BLH+f9FSP?r4F=3RBcO<=al4G}Y)_#BU zuAWhgUiT0Dg2(!{hfj9F&SfG8yVMw_+BItx+wmT}oYEmLQnji*&dLVjpTWsP2Pgn< zU~66Ujz{w97qC@^$b#**_*Txdqv~Z_Y}*dp(L2@K8^~V&rg!Wvg>Q@EbB+5!g-@*z zrc+elP*er7vm_fR-@F8|R|dmQ>Ec~N#)GCqD$Sp2|AUWoGX0tv`zTc^ldsKIf`)Q7=?YvtiC^kGM|7I zg{@r*4HN00$(oX^c3yTK+Qgv5OIzo_cCU}$6o``RL z9TrLF)r;Zh^lmt^XNfpA50@KOnyQ2E^CPhU)#k4DtJ> zC@**0`xZU?6+a4$3o^;!=YE}YJ1Ce_f#-ZLud2$Sv{Qj+ea!ezJ|n%~dm=0k(rcU3 z*4(0wIMc9-FXdnfb_&)o*5`Yn_^MbnC%|aQ_fE>NBgEQVaya}HFNT&zdth?*j_F~q~NqC<{*wGdP=CyRm_U5=&escuk&fiD4(Fd#jPvIIS5@Ib2czC z0DB6@ih>-BkGbcV@%vY?)y(s;NKbTJa(oz==53bl&?;jRG+c_80L~=tR>OW9?0)xlDBjvy!Ohf)6fPY9szzc zd{1PJ_jH=rnvbPDEOxi@$8b!o)hB$C;C*cqbL*Ba#cMzPI*k+h=2_2(aL`5waaEnWZk z^RAv5LMUpyS+roi>C#W}-QM<7I9jD|S zOI5o0)F^n2ZRx80^Kfsgq>=M!Oreoo0ItI;Kk=Hj{u{KUe9fSgYw|a*QOjcnScH6S za#|bG&d671Oa=d5UQo5|5@ewhg}P>{y>d@Y%7W6rvjQzV1)R?8?X2>p!v;5OIJb$x1ymHdsI?=6a=R{TV0UvFCY>!aXc(m zdmZEf4s)AY1#X$vZSf-OB^f?DK2scq`JGl){KP-haTxSJ|es}Vq`N# zGuQeO@aqOevUoE^sr?(r_`(?{{9;2s%Y0#N&ppV&$gv_fOkP@|f;^Oy~OUR(V`!kcO^>+Z~9nnEcDNlcw8yQ?%b&I z{*t*rHtNZ54SzDM_+=xaIPex#+Q+bdn*rOZttD9{kax7PDM?sAp8$2EgEumVxTKi1 zS`-2&7;MmRf$QYt6vbc)D=6d?ioAxk3?8@P@GW8GXXNY4r3^WV12wm z;7g*d)zU(Ne(#fi7ssLXLDFxun}Rhy zUGh;NzUvJ2MhW-?TCe54sXKh35bc@2ucS&;g9c(ubvgP6`Shq%M6`^6<Z$r6h}XZ_j58(Gt+Lw&&}i8peHj%~p8 zpCo>w67p=?RU;PnzmsV8kMOc4i%5C*NtDwf=Y1Y|zeiq+c=@YQhYUTu;Dp!pzvP}T z5i}An7=HFCKT+q2{n-?Y6`e&a~ z-ADXvN~rD{x$cpu)qDM+x<}*s?f#qV&dYVz7)K!GHKhD}-T7MLWi*Fms~NO`s)4?B+OR_`p3;*!L@QPIA|5+GQR5ko-G6>a=?!)b5C+6~X)IchI|DJtui)8G z3G{5JgilbyS2s$qh!?-o{A^vre)cJ~&G4U1xw&mLsP*K*wh6=aq#w170&VkvTVouK z6yyKcHi}x_G#tE8I3tJ;12-^_VMnzs17U|aNR7!}1o)B|=Cz0%_Hw`;6E~$ms)#2A z1I*a4LznJ%rYmk>{H6Pb|Hl(VXq|AyV-yL}_UlI2?-FEZuCK8j^YhF>8+)ElRMsvM znX%lV&lY3sz=Q6Y>x#*S2}+3#>+-}ApY$xv%Wypr&(w!*lHGU~Mu~Hn7{+3R1P@-UX zFWqI~?f}mF3t6FDx+nMZLi)uFB!mwA>sT4m6=EWy7g5ZX2Hf$Go=3G@NzfVV*kLIte16E1iMoF zq%bCN4&=gNPQEZ)G!*y|aXif-l+}W#jmEya;^e%tn8Z9gah`33nTWWl@ax%24i>Z2 zOo`p|1T=o!pH&h&ky-_@;Ef*z*7-v%u?IG(#2u^6tkDb#c%}TjuB6(g1z)DtFDE-!}?RcPArT^Bx%mWPE3Kl1D7_=Gx04d zhrYIrT~a0#d>!O^@}6pimQR3w=8V)3!zA_u%DO8dCzb-iAlc?L#C#k0)z#3|5lGO# z4UEQJXW+#k(pZh_7rsO7Pf&z8tXK!e9vPdDc(y67cm4TX6kF5h?_|6>F$+?jn#P{M z3s)I|V!S0Vdc;Ja7y+SHt(9_w9f%-ME0tRFCnUGzBeHM)*wc_y)Jn6=w7MmTY3R{a zCiB?985GU_==5YK|;bMF<$AwspecKuM_fWrKgHQ2A03(c=&}|u zx*_TVYvw$xdy`S_SPs!E9?2JtaBL1fXUsae+22@v>vC|N1l1WXtFbsN5cCuo^RnLP{Njk|M{6}zc@9nrU zi~k5N>`f~y0Pb}L4ZTW{aE$$f3D0Ntl2$Z9nJo4L%c!;=G%iJ4@G2XyLSN`U5B%Yk zd7fC?azr|WR}u43Aj3!4KzOuw)2}uyU3aXJ?kjD3*3EFkmfH=lYYz`^!`12Kl67Gs zq&~L_Rr1I+6)q{!7cAY>8T=A)?Ncz0+5?pS3(z!E+2|J;JX0goU`!cG@=~i2aUtLiG@vw zIz!)zeIliq<|^L3TbiqqwWhWUm=N<)&eJI!+t-L4fLBYc-Liz0zr5%Zn# z;@3oTHgB|=x&klz3C_$xIG1f6CT_QlaPye={P0aIgT3or)T%LpINU;`3=xIkJGWu7 zApUZ_u~3dyhS^T@`ock4xfQf>RGTh67uF9X_ahvvk*xvLUQJs$AdbZtSwAp@y@bI< zHz>JW^U1(ejNc8DRgkyj3coB_T10nCN|=<}-G7R!h3yPkL2h+LT6fr@-R08L0;Q8~ znj+n7n7nLl7UqaOGnMG)r-dljFxOB@tz-m-EGZd!v*N~^#{YP;V(`sS3X@b0n=vX~ z5ML}xB-&n&$Trtr#_Ti@90m)6&(IRu0m@N_x~e@(O4tGG-u{ihUXSgVAVFnz8QoE%=nm7{W=CYWss*Ap;H|b}m{{F$U2*j~hP3 z>QE~!faS)LUdoSA#4Ih@YTM|JD=}Z;Sk|M5f9H#_&ma%sVxf0&0&6@O*mjjQIz<{^ zCj;eI+2qNPzp@dQ_Wgy6SNCBrE7(D_?JwMe>nvQyw%-No;ti8AQ<+0$iQZ7o$wsLt&Z{~70_?D8ZpZE{=o`e&e~09QRUCPR zlI7-x$$Ls-yphml4EG>1ogCv0dw4-gH_SaUEzBJ@`yY+1_cLkA^BPb^n+I4k_%bgm zw}>)1xkU;2C65S%&L{PQap}~MmHu;pJH$)uFauWQlL2rkjl;2`kW}*J!%X6>d(&Q0 z!2US(#R>Z^N=FWlslBE4>)_6Q{?;-vtX*LmbI>Aw7<_s_eXFAVmV=hj3e$(dr=TS$ zX^8VP97dC=wehHbW(3nYrTo*&244 z-{U%fqYoR`4d6Tp4Cq5RMspLn&8(Asn%&OYxS8AzJbR5j!oJJ?oz-!}IRnfH=!dD@f(S zd|p02qxdvo$v2tr|kKH^MdD#diuxu;6!}!Fl^j0}+ zZ0WpY)3OrKnvtX#!7Ay4S&Em&0M((W|5o{X@g=Er2Is8AeEU?_vBv7J=-p+T#>naC zOX2|Yd|>%Na6Dogll?)8{1s>o*HKPb)bo2cWt#hf*hv9vC9Rm5d7XhryECT_(4Lvq z7ElDVGg@D8g}h=So^iiQF1>CG;`QjG6xjQH#oniMS+QGiWlE@teX8zBx*A=x;;B0@ zhg&<(%@yQb*CvYzf6$mVenz#bg_dofd{r))8}`ywOtSc( zMPXVA%%ZrFMSV(f|7YtfqtmRNHD%GaT04JRmQl$YoMZxbhLM1#GSlO zy8}bd*Gu;BOcLS3(}UlcXD;}RdgxeZNf~`PuB0a0*;!mxF3oHBMMK>M-CY2Yb17utuj^6^lo4N#IR7{0<6yIe{GhovOx{trbQNL-kA*0D3QFTDGK!4|@DwYOkP^NxWZDq$T{}bmP+d*!0tlTq@Jq z4eu4&`+-K>ulnc8*jOvgH-Ak13EHDfnlJF6S`}8F3PjNEv-<{NV zTeCNw9#cmp31YdlS)eh*`rqcR2j3YW9bN(KfBJ*B_dGCI!e;Y)%rc=70UPzkV-atB zIdp%-ALkoDr2Ms4tgv<@XIRIu;?0?Li+_Jz`mVE16ER5uPIZ>z?d2-8Qz0x z^HyoRp4N4RxE20#w5rx3W@91gPdx=_mxz8QDZ#s@d6<7->bN=7u1kK|AKZGKpAt0@ z9Bf3F=ew_#l{^RA-RH3D%5xHjgU6x3p)`AC?E0>8X>1KBLS6G{NhuI_3f`1k@MJx$ z_cyrR5UupBpK4iO@&g}CvjI^v?396Eo}`lZjwcJ%$=8M`xi#mWkma#+5)^4V?2v+p zuL=dW_v8@^0`#g73!e|7&5B@A@Lw(c!ELawfc$b>(M+<4-7uL0$Ff|nz;O`8co(9_{Qnv#7EWjB5AN)vts+H#i&OBY?IrVf^b) zH?olFR@)wP8?hi@gzN7hs$QNOY_gqZj*uwZ^{tdS37RwTeKXk}iS8HGs zeV)W2+6!UlFRm-aM91{bRV?KD=D1Z=Hnr!)!rymWA7&@Pi)kD?4!p^@`a)~xqw}}h zt~L&HQ(nsDLHxe`{;!!VTUH0d!{b5rKm|OIfiIW&ZSuY$+fLXfNWWK2RJ*i1lh}%V0n1xmRqrm(C#g#}c&%UBc8Ub&4)h_jpDEC{~ zr!h`vyTT{dH$DhjAg+9|sPyry#{X;XqrmxYq966;H|P2la;eMfrM3EcsR$k|tm&cj zT4?*PZw>QDaoU<$h|Q4+s=?Kx@#iyi_hIl*&r#_Vb27LNTKQRSRsA`Icy?Zwv*=Xt z8Bk@0=3LQOz?%N+k|3N4K6y+mu z9Oi`OL+nbLSJ)(dp>KEQ71G{dj4x)Z#-E@L^WVY>rX=i(pz+_S`Vf08E|Lsk@VYZ~ z2Go9IL9+OsMTI{8y+pXuTSnjK{W%;{bH0*nGJr`uS9=uuiN0syYbjpbM}e0Ds(S0y zX)EHa1T~vD#dqpc4UHbTy@r{l__ls}<}=OS+nej8k)Q@C!acK*k$p=-m^8P4dguEY zOfvc$X~)ols^oUIeYc*T*FrJ}^)z9|VuNsFzi!UG%46UX*5T z!pu!&;cIL<#*9KTyMzLT-@rzie&L(jw%{|gQ)ied)J{Cw>5flH9;w=^N(67NB>Yf# zMh&)_`ZHjYfVZ_rB?IEbK6hEc84EQ2KXP~b{{CsG-40(Dnk{mEjp=(YVUk5WiAe23 zqfl%5!fPwh_*bh`chocb2p!V1kSeh@q{um>J&M=@HSyIcX-=W$%k ztD6J|=Tji2g0Uc7yxXTA{9eiRBFu#ZC$$oTy6^fVu|RN~cWg2;wX?-fyec{MqL+G0 ziMgfSnOL~A>P^hNO&E(G1#b6+T3Ba#9wQA>=Jie8_AOT5-<;~9@qw9T1~}ae_s|#_ z8X+fx#v3&YGd=$QS+fUj)QqV)Dn$u`gRL2=A4a!azjX0oioApQD7lwrD(cg4)GOta zDdJ`?&0q<=>gpU=Mx6@A^$w-ReWKpC8t>6O7T#MSI*|^a&|{~t>#};!si3l#+K0+f zesU4dSBi_gYRqS=5sl#mj@`jktM+R5Xlm&lX7@*d%zzSn>8aq?J@od!d*~fI?mz26 zpH)x10o5lLEoe3B8#5mt`P}77>Mx8(s*RP`)bX`*&|9~EqN>kDEdMazixOC-{>1#F zUgNw}4;q($x%flx0n<2D;>W@7udzwVV#rU`hrMSaMGiZjyt4S2DkgQKTaTSXH@Yh~ z?}~j|N@m{Q%qNfWjB;?lU~i3Ui>R7+Wz>YZSJdNM8t2}sZmV4qFI&GXeUwdK`tTC( zZ=UF%1S^M0O313>z=>2|V}*I%XxP!u@n9wKY{wp(Gd*x~x?SU+P;@(rHpS1g&Fo;+7L45wg4z9o!zexp{UGh5&OOiXQtbLB@NfVe ziB}IEo)Ktg7230_^6*EC!^QHd?55OB=}q4)hJK}qc%zT8Q{xn0_jx6>&uVC6>E0+R zUR52M>>Jyzg2gL#T&^ddEv`1zL8*%R$-YGF&Pn-L^g`w{>b$p&Q}rnyyK^elg5W)O-QZ%UytQhd&EHDD;hu7=ponTt7T|I;_N?lbnw6FH;>gu*c*aWD~qsd=B5Y zLep|ly7Tb22H0FdQt*IB0o(WxJc|48oN66}r-tB}d}!4RfQNno&x8;>iu>8gcTW8y z;F&JNQ+=J8beo%CBE6A-IW);nJlkwQwDr0ZBkd9F)R)tgi>nn9&0x^@2knyJRr}v# z7eG6WQG@R?yV;!|1yX#JI$t8n;$CU7Nbv@Sxh<&G2f=06(QCxpF$&`C5Sf!~ynpZq zfBG=hbCgJ4w0w0qVsyd|x`9b$eAUjQ*r}Eo7mG+Jr<}iW-s`re-s#a`mDBhYEVKJ= zU($ucwx`a&A=5v@`rIy(mW*=q^+Wr0ZpVI|n_WmZFH?n`RRTYryF7#Wyb`NKR}ge{ig`ylwqHTp8u%b-Gz>Pt@U41GZ@e_;t)`XiK1 zWe-98-QpKrQ#bvFAhshCmMR?ahnR?HH$l$SFyjdFr6P;iV&C+eMGeM;N^VnLZeIp# zPpDlvN73u$RnK9BsKjp#Q+(Un2@eN?EBZ0!idE@}rAEwfQ+#XA(GGN92j};s6>3az zb~9p^(w>6V@Sv!u`p4q+u7ub~w3V5mo_y>Y>;w@XP5`cET0aOr`gSIEXaOHOKr z9v&rfwXnGdH}SSvS;N;JL1ZJU59|scN46e@ExuDxgSu4{<(65t6ZMSpgcH~oCje~vI#e_)*TN1!^^RS-Z zFm}NvHZ`pMNYCjayr&+B<8DQcTag2_G(VoAsZoo=r>>o=i)!R*)Lu5@4CZzCZ=2af zzJ>!0niHn+k7E@bWjN+=*n_X3u}5``O+4A53x9aVy><~1RZvSg$H&gu4jz$M*!0=< zGm;^adY^po43QeYDCfA>!A`vwX$R~_dg}Cbws$*JY{ZNc(t)Cxy;{TvpTi!I>WYr^ z9JIT7RQhDZ(cI@j5vQT6o8%9QGym-C}`H^p-kp`VR_W8EJHlT?ws72)1KG$xP__^zc z(bjv7MjK;#1{n5?lmah>5QJf3ask2fm_+IKNr?iRJ_Em7VEsU2m@s}7=AU!n|kVm*~=mE5vuTeLHH2AUO~5_6|l_4?`5G1zuyQS;@2nW;Dy>H%*L-IRN?oU z@F9LD7(c|f%tn%P>K>l+aM4WJE@H+RX~O*Hz%UkYAEUlH_7CFQ5(7%?Iu4r9?@$(w9=nMS* zYGUHVIR36_MO@;Ri3eM@ByEP~dJ8}A%0UIig%~ZqU39&O;$4tUt#VF$CB>fHkM(9D zWLF%|Q~ZmTk!rHHWyY$+BoRB;#=Z>-Q^`J9pi=zqI-BNomFI)t6=`TE z`H&S2?f$sVRq4>UJ_?@e^UCLs`-p-%gEdia{V=fg2z0UxqcaQQ!Myq^ zk7t!fV6?+9EPhxfw-cw_PKdpBGfc!E8J(a|$oIIGpCKoMm*t|ElPrh3Gx9V1P%+G- z6=C@O@w4zK!&q~UeKo^!yh5o`sWlp{P8Sw7EIfReJ|qvzcrTyO>?X=CZlGTyHj^$jVIQe2k8L z_~A=9KF9F|jxTZi8^>2TF5~zb#}ynMIKIL0EspQlk52kn9Yo9;#;VfDXASc>?y7LG zxMvxie734qa+A3VW&?9SLsy(4Y^2;UxEN|9T+-v)CQY6)>GsS?Q_Mng@zl)B+bmOr ztR*Q-@yfi_%L~>B>sRJ&C|LWbkhJ~|VZq7`8;c)ZnJ*;e3oABlSh-%H!Dv^qZ-$DEW2!i?n`mjCF1Z9Pi8DZ|1I z%kx&@N&XzXKD~J5qs#Gy4a-;4qhvfq8DjCul{ekadKBNg`9aPD_uNQEA)$03O<4Qb z%3^?-e6&*9eZ~>xC67S3W9#;_>2w4I5TI`jb3&2&6qWvuT#mugf5=5`BNVM&yE@c5CF5Pq63ch!bj`NDlez4Akc;0i6ZQf^=!v*vMTO+K^e-dXqL&b>n@UVc{+ z5ahnB>2l}Lm*jlH%96a5xTHqai4V-0A($-_lS*_CuU`JhdI1-V?!E=nb8(fNR08OW z@^Fb}ES68}i{w*Y(fXl#`9jACLa|v+Dz=19>7i3b=rlQWni4uq#YukUw$OcM=yZGN zWEm=Gup|o=1+WA`SYMQeL~~}zPkyK{q|uu{lc-~mmK1tN$2cC%UtYZCAsofR^8EY| zMxcgy#giW@$S(<@+lr0rfe;(kGt(E(64tL?{@6-kWpVM^V)=eU!J3t8H*S!x^H=7r z%^ynCQl`~wAGt$Vy_V1quuKpf1vf4W@^4&*nmd$-nLv28VdMJ2R2@^aJSqP!Bqo(G zMfo>fI&QjNedGF(yy6?zN#^v$Hy;y+ZvK~xp)5mZX3?YhD<3YPSx2rkFd6NeWS)%1 z!Cc3|`yP7%hGuPsp3r|gtDxDC&&Qcz#xrAarmJN6o?$?X%Ws$m&y#W1DT)|6fB)Ar z@>$6+19Z<0aA4XMi~(b3+a5{Lks2etQo9= z?zdKK-%V#Mcq%&6iYmi3SguZy%+d1;Z#w02(adr?6a4fX?f0{AxnCQq?~QY)o&Rs) zLWN|w@Jaga|4VQ&)DFPpYDI`1X~5YZV3@-=e}A1}4&pp85IR%FS8$K&FpW6(;rXkB z>2#)l2XOvp9K-x^@c#d>_a@*`6vMRf3c5;*{#BAc1K$XQb5NAm zUxcfr@PV;XIEp2O!(R+vBZXsS+Cz)})slbWWZ56I=>LG^Z=7O=8I_3$$r(VI9)F9lG6 z6yGSqC!u%>e@YGyM+FnzAk#Dt5UmlU_-d${Xst}s#7K0AKL>eIKO;KyI@-{apO?gZ zGPc8)_=d>-zJY!|l&?Tpeqs;*IzK7D+r@G+cAtvk&6mSz-k@-rHwe*gluxtF zH%_k4*)l|Ri21h4;qNQn7u(GrK_*-f!@rdI{DgLq{$6q7Pvd#z{de*E3H`+Kd0})9 zJ?a{NZ@3qZ@8SEO#b<1g*d9Cz2~y7@JrX2+Z|SLzYx&SUMLvSWxBcJbtNS30ZEuNHezU8o3i0uO&W=hGO_hS?&l~?(02rM@w>pCAk7SF6&{0 zEVu3&J;XCUOp+_{)7}WtUb(OJ=t0UCk9nWM8)4xPw94s^=Oj9oAJItut-M4dSWMr{ zLPdVEM=6}=Bs!Fn_`j2BnkXqenk9?;eP#adWx9|_{G&K2oZ;s#h`$dkRDv{*5d2c6 zlVtwOGR z|I3VzB=|wlWznAjll-OpkUzE0+5ENh6vvi@5+6-z6h2Q5zuLd94WBQEd;972@$Zzw zX^V{HULS7mNnaYji)C65eo8;MXMFdU@~f2cOZFPc+cJL3c!EF5{erPJv3@a~i{Z!L ztjncv{j7nq9uy+<=4bX{DV;lHx#)jNNuK1NBm3)N2arFu^F-K&m*psbg+1{?u91)N zK%|euKA?E(LL@k%|My0USKJeCgxnvt2a*5M9)GFb(`t_5H!{5_rx61J(FJn(zEv6r zN%=B~{`^bxY(`1GuPFDt;=I^SQ!*vFn|tIGi1~U> zrg`=_Pja4@=^s#jqF<0{Z@ylZ>2F~dQ9AP@B)&Ige{cOAm*em0@%QRmO1GiM|9vr? z{<0l`Xd>^Ppi-zLeL6t7O_cFQ{djS`_hXyzyao6YV3@-t>I0qy4U< z{jZ|~uA>95ql2!awKDB3PoL|;gRi4QuA}>2NB8SR)0&5#wXm<7d@!N{PMU;u5J76F zFym zCiz5r^;5ab#@d(L*w%Y&>q!VBVmtH4Jf8$-g97h#{r!Loz65!V=b45Yf;DS-u$zFktb4Hulz(fK&{y6w3)8n+N zOgeVc_c|A0Q>>->q)DEuLOn}~PaKtyP~b%@dRAJZXZgALdX`&aEm$stobn1URw`m;1aD`z=|cv6KbWrG1e!u_DwVOB}MtAOT{CO6}jd4mV%`V^$Uth3k&q( zAz5xYHGo)D{L&=_Wy7f6y%Dnt3$6Mo#YM=l$Z8-?V#sGDMN3d*>(Uj4r7VAW84mQ& zN)j0kPLPNELS`+=$;&Uv&%x1VVFAuBb5`UQm9x^Nx#Yj3cxhQ#&QgpJ9lHof`0Baq7=}slX@{JCvP@OIf`tI5 zwyL~i9qS|e&%J3KtYT)Q+2uCibAV&!XHSe+$1uE!`8+gZ9UCa(FNkuzAH;`QE};OQ zGwxa^QY7CD9O6YMddeRO2^MfKXJ`A-O90@Q-RkN6iAu>SSYBey$z8Z`LD7Px6fJ!( z<;*6^x(J-)l0DcCoYJRI)m!-9nCP!z{ecTI9t&J4#~lxx^h0r`0jGXSva*5q2NcT> zoTfX%i-3p8cq#C3$f3A4;LwX0_i^9@fYY-JICLaF2Z58VNY6*W^?)Sv6!5{wokko< z;2}R^Cqz?Zbkd$*yjYLsSGC@3uM@hHh%vOKpK zy{Vv3W}&f1MloP8ya13>nu}Ksu3|{UT5geeN^6D69v`=bZ-um)F zDONrrm5S|_&F#@5dwlUau^m#ITL+x#pZe{Ci`HSkUTV)?IRtacr1^#BnEQ}kEFiVd z8sJ0Gf=Ev92c@g1#OX0QO99GWUW9y?<>%#;$E(;>WQNqJ%E0t|^c`K5)q<%PXGO7RlKJ%uc?PU!+hC$iflGyphf9D!l=Y?qeviIhcv6vR?><~ zGD@sVOYvS$!lpM*#QyQ1*hazuv1P*= z;U5V2DIoer4_ptL%5gnxfIsQG8j$+t`!ZcrSVAw_2^M-)Z#F*0%*V&rr}1(7ahjsH z<3o61_R?DI`}pu_#7FQEyrU<)f)C9ed??<)2lqMxLXH-}jw)WpmMq0slv50|8}wTO!` zrH`o@bEl=v8_CiVr7`zNIY`RY%(Ze_&uBr zIx(_B;BCOkzZ5v*C443DIh;oHe;D{&8Gj1+O)~x>@Y`jXyMfagtrBuR0R9eVgnWU0 z4%`S_jlb`Jf5{mIvQ0XGeUG;4}^v z0N*a-4X{P00Vn=t@OMBCm1`aF78!pIcr0>8{=0!6kjwH{;KSfY{zrhnD9daD?oI1k z;0HNciv_cP)U0Fgi{-+(H2fQ6{5Rl@NQ?5>1^ic8j$eaXjfIlYVi-5Pw@*%e8v05sz@+!`;7M2z*Es#4)3Cs={S0(5` z2+t{5US5c`X|A+r&9&yj&dFPWS)P@ZE-fi7yhr3(SX_ja5Z23O7Lk_v-EwO$qF}`m zkwRifvlj}xsyMe&^jNU8RGiq$upAOSN-K(%6=DrTIT8Er!dxtr5CJQoF$*Or|LR}z zhXKp~K$4hiDbrLewq$t;tN|DpB`hx&#w6B(3t`hN&m(HgLMndllJcAaGH}W8#4XqAXSFcuQs!yp*sxG02U1+u-M#@GiTmt9sT@>GQ**}FW)`;?icPFoAc1!XYaD+^t=1u#=~Xm z{OX+4+kP>{Ji7AHibqy#Xnyq5M?TpQ`&jfN>90pV@#reey_ZUFx})D;171sc`@i10 z=e3vLzH{GquYI&{UE}z=4>vBmKYKBS#x}%eGuAs{(~0;4A#&*^lxht z^r(v$1X|d_2Y)XL9>oamMStWFvm0rjjLeEC`rOg zqRf{d&BJQN&u>(e$`@BZQTtTyrv(A&p2qmC5phAp$%o#W`5HUS96pWUIYqn8_@oi~ zYw+XAgfSxeW)@6knNw}>@rXVgyQDmgx9JzFICZn;sG^azvINe?o#S%(ZoWa-sx@j4 zYQO5UJmfFBO5c9`^L(}DE^uw5mN$i%AyeF4=*37ES-e5|T*}C~nFxxl2Xq`p{Qc_{pBLFeOSQr<^hbh8@FlCr3Ol?pn zs;8?9)HoN%**FJ>a}2m{xE|Y^8Vwa+0VlvI;b;rK-)HqV+U>y0}0iWIvb;Lm$ zdw^5T@>E(x$lK&S!yaKep8Ysq5#hvS@b7JixWY1YIp;HYi1jHhthxi2{l zKMNrjSPF0}|32@puz-)kth`ZCr_c&IF{Z!~&swet5(Ip^rx<_R0oUU1OD>v^=B>Qs zPhliklCI$=@)8GeQ3_Hj{)*cbV{v224t9!7<#uy_=OX!H8DGbn6`v?lgdGU^JGYMi zM4?sgQO;AHV!J_^K{cwjsI3~E7&DS5p5cn!kPykQ67D8?FigaW6B zhQgQ7k81(NwL2j3xj(`_4WRcSKN><2`~Uo7i)ZY2oQ?dd;+YMOtphGvE`*0a4f73v%#_3 z0pZvk$TJ+f6A+Hwg*?Hry8+=a4@y%Oeqx7dIW4cnFrigyRa&)H-CwO&k5n7~v{L`4 z@&8o#zXbkyUV5{;(Hh+-^Ldo{G+;B}A;5P4_xiD_Qn*fh&(P_MUq=I+0JzDAaqE3p z)ddaXE^0snZU$TgxLCv1mJjAUkv^>IXXN8&EpWg` z2AH}VU%X1bKVdo4hT`SHmidJGDt*8WtjzrP|7)|q}boQ)< z&9n$Oy*@(t^-q02>8$KsKpMlo03>tG1BlvWgZnGQ{cEy|yidOosrdFR0!49393zzH z;8dId?YfHmbUqdXM_NmVGsDri*4uF$-ss_Z{GcPp3kpHSD^&PYsx%5gqeLbsKlD&C zG+t7E&4M-SON#7lm}N9oc#E|fO$Q~JbXh6{tEJkTCuO*0k3)-z6n5Fe67 zX;ONW2F0cQ`9CU?UK;8-^mx3DBwC&v;&T|cITV9~>5CmI#=-REkS`8$ImqQ;mvPui z#E%d&4*BFTqHsuyL(AqcPjJ}V<&Z9i`GLC?Zay5cam_<@Lit5pvEHcse?}t@VmOtF z>iK$_^hWWK2Qi#6K`bPfG&ms7D^r!)H=;(LplHy8z*>Wo#OXw3uN}FN&goGtIiDSmj znKDz4?H~P;rAtO8B;ef*+8?5C-RcVp?4~1+ zb=O;e-unDKKWanXxZZmHJwIw&UcTP#%j?&>jr}`*lvnECz4J`%jq*x<-n>wo^ZNB} zcN9*1l&-h!Q8@YaZhsU`ez9=gHtF?C?Bz#iF~m2qm!G$PkzB9tdiOD}pSPcpE$H?0 z_BBe^>xc0|OoP((`q9|#P1oz^)gR^QkNgnyf8?R}H@t07n#XcV^2_K92zvvo=xj!7 zq;aA5gSkTbr%6Js7J`CGic0X3Q5jy(0mM5tW#tR-))1z{vYg!I(02}Rc+N8+xJa8bjrArE>;uI_|ugtH+8wWZ0`HOM7=%tn}C@ASgLQ*dZKhscJ zg6;qEikv0bOGZqnM|^>zYz21H#T=C}2^Wv-uJJ*v6@^6$E#)#teqnJ>w&gf@<3K8g zL?ebwqoQy5QnWve)PL^=j>kxCdJ%A%^a#HPI6_38zW_(S7J1eJr+!I%j{>K*LlU+D zr#Xw<7U0wm$bTnr>X(GS4xIWP;k$uT-z0oLaO!`w7uNus_D~4_3^?^SO6v#UH2%;T zSsQQ~PbiHp;MCtqj{jE*aeN_s0C4J$l%HY1$)+HD0&wcr8gOO;r?HCU-vwM658_!7 zaI!y052e7#jv<*g;AG1X{uppN_a*!p;MhVI@i&3f_7(ZR4SXQ>{wUoKfJZ@x8tinO z1Rf1P^8X&VLB{_HJO;R^-@i%kD-qrYxL)=L=y{3?Ffp-mYrgbaUk=`@Sy)(3ubVKI z^pkY%O8MycTC5vsU%4kX&iX6z*@|3iQ7x{ipDK z8~evcHg*N>p~=uE=mUU*-?NDkF2UdXRCyHaF1YD%PVmr^@v)6v1YQXE0G#(}_QkvL zel)A#J#pYa1PZL)AKxE^`@N@1_8%}X(ho0jUh|}!{^R^VvOr+J)mE|kC#%@VXQXHk zY^@TJlko5TP`e96D-9I?c(iYSv}Fx^xPJ@x1*ac4={pX+aUYy&_Y-9*5qcHB%7gF4 z|3TbP*1#Ik;`^XS{_oGtNi7SH|NGWxT((a-wePjgM# zeXjBE&C?sds;g`Hf8U=&@03O>f>+x_tid>Fd(eJA-Q{?9&H1{Yde^y#V<4!&fahqr zHYC=-*mew5I&9L{oTo4=hLZCTY<6Hn<69a)ddC}=G%_|uKVZW0<@k?_TR!0qeCAHL zBNs6jFq2;~d(pRy`TMS9_xV(@HqAqw>#-HHU z@;`HVSQ8p~J^qZq^5C-;A+LesD}D>OanUGZ-VF&GA?ZU!BBVw^x)!N$+y{aass4=A zPazkdAU7W%S8pSCuOXK^klU@u^+x3WA(WyDrCEtmm7#RSDCGjy;+M-_^1p*E2)KnM z1kPbTLAZamM{~wOr@p0cd&RrwN7Vh)gn=-kYdmhbla+4~}W9_jxV(m#_vq!AO3{T#k~!fwQO zushjUd}DkBzG#quh(@NzIf)Tt`wuvD8qupPVk;0cO5g8lQd|3{x1Cos+NJi1k!h zx?7op-`{2c9J8Es5ECc&_x~!EX%Uo$ja9L-B*-^V$9UC}^sY)!?S5bhQnd(nC%J zc-q-h>IAl#!E^=B4)!y*m@5R&B=!zlkNiY}2m1NlvX?SglHeH#9@6uTY$aOG@9P=A zX}~6PVd@L0+zZ^h{G+O=z@~Ck7p16Wk`pVZg}P9Qbpbt(k@e%@N;wbmjNbrYr#XL* zUTl#&6jQpj(36%uub3}m8nn%)|K4kaf^@v&CbmuEp!Bx=evS5cH@A4=m-Xj8DfRozqkKDO#8;mR)Q*v{A8a6-i;qY z68j3-%nw6{1K4=joO;DQ-Ei+uS~+b%J|O=9$R~yA8|)`_xCY!`}gqlxIKwfXwp-%jw}E`&@jk%QN{&x%Uz6 z?LXrAm3HEg7TNaV^E+~4xESQohv{K(|Ngjb?Qi++yu#ks?3mA=`u6&9`)WMnpmjfB z1__IIS19X#qB-629maOpzVmsE(btXl_;DST#@9bk8ywnC7aloKA00Eqo6Y~g|7hSp z8u*U}{-c5aXyE_L8lYcIR+`qCnw(=DEGiaoQj36FmzEU0S#;dl(ds*@%GB?4(5QY* zv8KMzPbp(-Jx=4fo{iG>5`3P4o-0^P_@J6ZhtJ{Kk4bZfA3N z6lo4#fnQjU=M4%wXW;DGnem1lme1AdFVzkmufg5u`?{R%*=;}crC+ONL;UPQyRnRZ zsa)9<&+Bv<_!VkqXq?WCeLuD34E+K#Hb;(4Qd0i=nYNhdw)oGSo7!2F8utw}InOv) zbQSLA3dvZfGg@{Z@Q=PJ?IYc%vu`#Za%*gQ@V<{blValiXAVpoWhVMhrMO1_x#g ziWXY@*-_`Cj%s(@>=VwP+Hm`kVP`%*73cERS^9iKfjX-&|4dO~!A^4u?$y^NkZszGqb#T(knWEL7vJXD*6<4_fW` zuLE>P@5va(4ukJDwP5o9N}a``!z`aU-{??g=y6Ae0lC-WCOS(4@lJ*O1C=%wk`=Nq z#2jMc?0sfLnuVm-TkaEfrn!L`=@KhDa?N9)#rVg!t9&Q zlWS*ld9zPui21OqyKAaB@?h4Kc{h!KZf3w$z`ccX>5x_X;cVE$8u0cZ!_5iPXGRV)t;RiO?VTYr^k%j<`@#db&51=FcKz5D zlx;Jmn1g0n>NDYU#M#xMx3H+A&TXv|EDZNcj4|U^?jOW$JQk&6Sl2P!oN)w>{8&Rg zDD8(`;g<)S;~^3EfZ`Si(sMb|s&BV1EyK;s zfw(nW)vPFD8(9>$aiGQ5QMmCFjxO9owF6JmN~;&+n#odMDDF0UcTZUqpK? z+n1b`JcHYu3`u%OA7B|$bi~=&&KV5mq^u#i5tehgxZ`yO?xVf@dVBYriQ{}tqtZRD z_1(vv6WUKW^IMps%k;B9kEwpXAYYYYgRiJUecRAuE#wd*BiJUh@su+Eh@*v zE74hcOSpw^wx>*pp8Oyz^@%qc%jk z_x3C5Q-krHnwD7XmA$24Ki_L({hm~?f81|lr=g=T;Pl({)_whFj|}tY4m7x zKOLWD<_tEB|BH(QCvb5J%ntz>;JfUfRci^ZkG32F5AN$S5bp`+-&@q_nv7`638w;@ zv!X3fT9jsjL&4?&zINb2mivH>Y4{}j_}52m%*%0qKQaWksmScR8h3vkrL z*_lCSTA%7@)*gI13g<``qeZ7PIMfPF(w0=*QL5)~3kBYp$x>$OEH$a&4Xj1Ohoiq+ zr%$Ex86Ay_&M7tL(-~q3n$aN+HP1Ic6ZTqaX44px4I`hz{@|SfZr;iz?n%AW{H*S! zRN*umc4O1nh$kW#?)*eN^@q5BlSK>mV7J=F+`NrT%$w$JUaiA6gMEM-+eh=b_&UVC zBW!NiFX2ot*ztpIjXWF|zdzO8%tqlX5M51>75?5XUN{jd6r-XK+l9%o>0Vj3XBnn#e5NsGw1FY24FI!|Vp!Qli<8 z9Qv@q;clhAuiFQ=gYZop=86Q|o1hu#Y^Ixx^F8Yh1ZKhhxcH$jm#n<#qaf~xm0sQm zk+-#(8|y#XH0=vm362N9)iY6luhNg$U^62$i*gcS37NUg5|XWO1o^Cr;0(c;xH0C^ zyIQ_W;budo;?AR3q!;JGSK~%Q+8EQcjx*7wceUA$n@0;>3WGX512d{)`Vr?3ds)L4 z)G5^wrA6t)p$|@JV+kqyQu759mtQ!TxBKdkV+=Gb#s=mY?nYO0%E2{@(i|*pO`di7 znneZ~bMISgQJT1zAd|`wr1H30J)xbdj@R<=@_vlc{`{U;6T@w@%^q&_TdA%y?t|id zImP4pu{&&5c-HrBt1T?MBRnkY_(lA}5pMfd;;t*fbXSDOwZ=0Y^O?~!9{oDkX@pgC z+_}POf}ekSBK&T3`lctquf%yX{PeK4(Epuu<1NZL<+w9vvWhT9ZZujV}?E7!c9=eai?}#LJm+%7;%N#KyG&m#+OCiu<}IT zs4Hk;L&-|>xJtUUm_-h|`d|6pec$%yEzy?KZWjO1MUIO`e>tHIjC-WSI|^?7J0jpocXxW|M!)?Hehe#mtWCHl}gzMZvKShL$!mZ{?x zX7BEDI#OVde&`(4UXWFod03ZQw709(nV%UwEX15YD}SaS&avEANfu_0vnbjRC3~$Jr5@CnN@2o}AXwbWK>k7$(KE9diBUN`j@zWG)(R z(GHG|RU(BuAcKQ!&d!S|L|C?v3^DBP>%zDjk-qK6=0mRAuZ*{xxX4s{I#)YujbVfK zbak|*WO0~3seC)obH=29WaP{rwCK5zPR?P|9di|TkFyAdAp5?~2U_3mTd-Knia9>)+QD=ffH#62;fi`p88P}#ajkJ8| zENk1>9mc8!HVb+Zk&nTN&nzq!6<@OC2381xPH6SG@IJMuGU4(`(X)ESPuO%J zedZj2mino4uSNTCJ_BBOG7nDlA*=RcCnt7QU%jtI;54px) zKH=8Q4zyb%!PB9^9C^q!=`!(*ynGtBn+{AvI9mBQziR+ zW*l**x=tNXI~?lCK0$VFvU=1Fxti1dqf||C#fmm#{@!-uQr4ucpO(ex7w57Yerx{9 zeLlh9&?=4s9(H}zbycS?x7;{WWr{T)c74>9VB$^V(~mfRruzt;c^xUR8scCjraEk> zQGz^b7&D^V9+g)#bhz>?ZheYMbr^Z_F}9w)MVbo&+Tw6mrafVs0$*X7)ZWaZ{GfGM z#d#iAqDP{P9l^Lk5VMdNX6zUSDn?xSd0btvVZ%|%&pOy%%1Pf2s;8B`ay_F3H%Zs1 zO-=4CHsTOE$nMAO$clS&)3Ij%(7h#Ik2{?{b53hP2^OW|zNqj#vi1Loc8l*;MHR#T zx$!BiVE{Yf=L_p>OM)Js+Y=hy@4+>~eVL$u-JK^@iT{x%^J)C+wYQ8r_gzk!Qx zbk~9UDFIehu7I$o!L=Lic%S3ZI>28Ou&#H%1?-bP+Gq`68>C)N;Ng1&R1;#K2Xw%( zMC)|iZJxFTxA;zNZHxB{pPy>HC|bO*m73gu(OeJa20q|hHAZH^D)<84?_6;nDeTm4?DkfvB8ms?XX88gB7pPYEN*C?NXVz zcn$8@B3WAEpDV7z#>Sfj`5sTQBWV}H*!quTseT7I^NYeu*l^(+ZgNL+3eBQbs#??3 zvHYGE+bWZTnH0^#E2!1Hts7W~cw?n_9O6ZkusFq;I4cLs$x+2kYHf}e8>?&Jh6pXO8Y6D7pMv$l0v9vTeO>(K6wLmarjTtaM|Y>) zOcFcM<4(2d&34PD*wxa*JO@p+t6)X)k;0Dgp1)@byq8Z6gqtR}$` zbJ?6n>Az#cjefxe*$3+VDqgMs8n?!6nVy#sje6GcN1Q7<2V%J+k?q=g>|L~IaGPBqsP8{iN%g-!U|w8cE^zB@VR5b z^HZC?zS^yvJ39Tab9V>RC&BNVw#Ge=xQ8%HJ#z%HY|I4?bW4oBE!v! z#BWer4*hLrq5XknTg`{vTHEcpG;_c}5^oA#vmbLB?QQgN3CsZ3wDv(( zKMud?kpNp~Jod-nmj`z{+>1wSY$RY9+!Qz^+)Vi8VQiWCfsIvQd`a2I1`8&eyK)XI zVvg_JdebLPwbO1HhLLNl^Gno6Z2ckJH&57y&UL8i8qw!|_|(8>Rfiq>E*9J*7@26O zkEjR{Yrg{)7TqLz%rzQ!5LOp$$NKvt4{;`6q1770`mwr*MUBRuT_i*QZ&ze(x8&!= zzpH!Q4^_07N zJ;CO}ySF~Dy29R84RlEF*{z3e z7sFu`cn{;nl!)vtrU?~Ff}BgJyWIp4{}u5604eD99jsMt(aJ8s$A z{JmRSWq_addG%(xhx~iDre3r88(=A!KAX<~evOgIck`I6U`v?Af0N(F(HZdrd@PFE zfQ`Ah$6M3LZ9e2mxfEp@Zb`8mb~d+-%;dIxLoTO#xFvo-lqpDDTO4*i^j7yT-M@&`W27%5 z?9hpD-=Lmpz4164tufBN^ZL8hfV6*9189TW07rWZD`?%D9bwtHTcG`yQ{`DY)J&_V z+cmG7cJn@UmbTNl_^ESJyV5itz2{Ts$hJ6G*vfARAKHd>Sz27)5tpZv=*2C8yEJGA zpLLMk`K8;q+iw%%wyXyAsdIcwl?cbS*hKhf3)z&PIv;LPiEu3}JB%vM_c~~I(0}7G z=U+Rjft_@ZZan6!@9?Yj-+C4}ze&@cnx2`dY)_rW+Eb0b?WvhQ?Wq}>_PPpnd+Kym zd#XvwYv9pwYK}W*WI_ftJUG#UboVxy{=N-UbjNkUUv`I zUbn2itF`5Ox7+?sS8FHVrQ7<~u2vV{)pr5kr9E`gE!e+z+wG&W_H=c(9_Z@6^mbQw zhi0SCrr{ZJnQ`e1x48T7KIztO$8GL4s;AUX9(I1`9FlJA2;g9oBzC*hS5oSuK@XE@ z&t?6AL7Doj0W)D4+UZOId)rs0w(4+;ucx#o6}PbBesoxSoG!iFb^da{3>K?vU{N#c zr_={$#bW>I4$GG5aYeBvf}}^YbC{{y^<1~!)Q8&0W2}MdpV|VgO};|Acna=sa8JX{ zKzpcwdk^EaKi-$6bB66}Ii@jLr&FtFc3+O)xZ7{DqTP)B3ZKo(eh9=m2_yZkMrVFo zP%PCQ-`wczau)xQk8wrL%KK}JVz)%scE111@btrOD5`m#261#Y(7lzl;` z6Pk@3p0a0CnIjV~JXYM4ec`4!y4^SplzTXQ6leUiFVv0?x#-KQHxF($wk}M1HZ`=_ zA9tz;yvlD5d{wbI=v4u87p2HHH98MEX|6U@`ENVoo}V=E2V?8EH$9uGX)?C@0SZl6 z^C_N9H9CT;zH~RuPB1B3-d5oLS*x<;7(qt%zyluP;sc7q?l19^$$oYYJA+br{^?{6 zyt@lq!ENJ`r%!9?l@B)bYEH(RCYab$jo3TU*B>wq#U2;FmS(Rq8DTT^&N+*|n)gQ3 z7mNKz^MMvFD6lDD8;dhKj@p7m_<=33b`M55qvJi?#D3-%|5_=3p;3Xg+)(5*s<+gj zSFwL5Y6Q7}Mn*f$_1q1<&4Jr!q*OKgZ$)hWko)mIhuoowTr!LOzB$=M>$Op){%Cn* z*Hi>!B{8UKdyrj?PDA7-GIcdS)Y zORcIlH2`g6OvtmTKCr>9NmRx)_#Nm&?(&c$pxyOB+b$lEG!Q1D&o7#qJBh9^9$==K4U( zvHHCaeSDzoVcgBDz$o18DALp)bN$_2_OO0{!67KhRwtMaIisA0hhPy-FjU2wtp}Gn zI7XjA_@sR{|L3@k{Yp13m!L2r>95CYc_CwB}TF0P8;}tWz4W)`f?>Owt zY~i+PqIa6}AJ*d}SE0zbpulOapvYf+8$u&mnStb;Tjt*kyJtIAN4A%8g%&*VAy0sus`3*zl1}EH(}$8Fp3+tK(+3 zU^2p5(L%$@mS4;))f-{`5xM_icqCq2uWL?i*d@%C9Ny+$z-woH=A+xpt5hq z2!EIKdz^U)g za}L2bGEy7apXm*0tBr;=t8E6Y-3WZmYMh>x`P$90e|B4AnZmA>DaC3!&*8@T4hs{d zh_4>%v^t$Ggc%L~h~;ay88r6o7<(EG0-eN_VV?mq(pKw{%9@8$AHFFqqK_npZoRfn zr`?2Pv-2LUn)A8R&{fy$wT;rQJb~tEfTMZd)+M-H+M!SP!~I&VJC`N#_r3EJ`V+ zGu$!WMAjR%)?uc28>Owsn#p~T8;Aa!Etocg{s(>73et#Y6kZuny8h9UMfMcEEs z8PaB38q$(d|VWvj0lM6BTP`)BjQx2vfDQ0)f)M) z{0(dJ0_`zzT+`4vq1o{8syO8-f7E_|_~`HkNT^|F-o+wCo85pJesW+_wnIpJHCO5% zuN1N2qcWxbaVz@A%}sGdI~MKCRU}efdR&2?*sL8z_@yReNE&?GjAbku`<|<+p+dS#qV4c(4yjnq@8OF7~jvWIakf?!uuuN2i+?DL6qZf;cxHhSAT9ze)W#(okeGq zzF(2-9g94!@4K0gZ4axruQ|7#*>|otRKJ0-*yGyQy|aj2Y_b})=ISjrD-gD6HMe=iS_gVnZUDp(^1#9%Qlm>ew-=V^nvU3OHvyjVHU@7z0MpfV$yu;s0w_` zxvvWCoEtXnwB}W#MO}-vv~z7oTBORPXxeGvCu~XO&ocdX^H{sta%0pX=k|8v-i4OI zmJcJMaLPI!X;?1pK5+4_8{aBg-PsM9hu&N7&~&^82YR-*P4*AMcxe zANI0YV~;b1xVg9iCN{jYIoI+?>Nj8Pv{)k}!eOOYB6Rt*%F<(B#HiR!YhPO9yt_NR zCTwHGCf#Nh$2$f-h|zWSQP+^m!8Mp+9Q__lt_$7@zquY)DfZh53*K_b`AM6uwvXjB zb{jvgpIRGY;jwZKwR7Wnq%d_0Z&|NHK4wH72yychSzK#V@Rko;p_is^O{w*>e4$I( z%nXmEmLX zl&AW}`87qvr8-L27TC30qlb-YivPkkEY-1S?LxaV?Dh)hUBUbpIyK(Xc`tHwShVR( zMsl6UH4rwzA*Ww^XJoMM6nysRJg!g=@5p|?Ei6xr^SLg$?sL3f;o~`1v7;h_Pp)gq zs0A19ZFWq2zxA%rO}r!J{m^ax(CiIspFxQka&g02=UoC|+*)-DuTfpp2(;fh`3j3o zbwsW0=hnoZQS&X4YlrTl^cAi?Te*Z(N9bB-SZ(E*O3G;;=*s_nXV^ED+bWam-pWY3 zz~l7$SU2zB-gn;B7WP;i-+K80ZpU1=!SO_2f&C13wx7VBh!EJa0Rp=j@QZMPwZJL* z3v4U=0tO0f3|t0W|H-&BI#OU0z_$WCKfo_)kicGsoLs=Aa2w&CgIfr>uLDw?2O#Sr z@U4JEdmX12*fhA?;O>vYUZ>$|*v~PD2f54P3gL2w2&@e5LAY&jB%=uFujnOnInrD> zOki&!d>CXV!z~AWcI;KT-n3stJoQk4CBT)z)x-T0Ze%R>1L1bT9fTwPnYwG^--@yy z=#{QlW-klIyhCN$-ah!2MTv$Nu-uRYX@t2xz1Ec?b(h+fm^ox7ZSd z*S*IY#wwNUu18`aBU4+~R`0;C5|HoXqVJR|8u;E@ZCLqZCH2b3#9le}iZ6Vv)#?^sjk?80Ku^;r zq32UCUWZ;h=TOA&Kb4ZntWxiQS}+n)Xy zr4ESU$#vs1QZFblMwKJ{&37MnE4CXdvoH8&W?oP%%CFehqVxmio8ItZ3-7nHBKyLt zL=VsDT;D}nhK{FdqoPH7Bm;yQn85*GXgd z`L1)7(JSR%f-xOoJ+0%LF3Pt?ZXHc%9f5zML8Yw0i`Qsyf~dg_Vm{{eXz*b%k28Ac z2Q!nD6{smv4(k)V5~y_wG+NO4>fy zqwP1|S(4>{O)r`x_M!qYeL>V&zL>Xe2k9?Y%(vUoTYqA1di0lmO-^sPCa2^7B&Q=p z-TKSAeGj@dztcMvX}n64$E&_wykqt|)Z&xtCd)0_4}PY1vK>mFeO;F>c}K>6_WTNM zRI-@wryYjMJh|snjfbTDSmEvYzjjjHDn}om_IIQm{Z4XSoY=SQojiJE`0C`k*o++* z0Zw)Dj*xd4Mv}o9`JkJ`@R_SQ_(WywgwKbaijlly>S`KoA~Vjx=lxCrJ{?tI7&#Tu zhDxkJI=QHjjXd6rrxFCCN59sYT-OKh&Xa_fkj4)OlIsG+96Sf=n**%D+tyuZ?}{x7 zvHd@T{!oR!5Cr-V+WkYk5?j~kFKGX-4h)3#aj;6VJ`g|R>YU@9dv1#q*ibk%+&_DT zU+w@b{+ZOF^x$k|I7c`H4xxt;zaH#B5Bd^F-5B<{;O!;t z9*u_VeB5o=qW0O6(a-Ipr;#F|lQj7R(eWPF@M~hI< z;|l5IM;~a32y!(0qlPl7yeX+PYi8`9x_he7663SQ&FiY`dxp0UNPr~^_wSPP)z{5U_QVNIG-J>%*z!x% z+V{5zK`q#I_79qAN^PyP2^TerJ1Qi;2_j#v%;%4sX`$sOui;4)d9r05EqHjx1N*5( z`_}KQh&T|3d>AkB_ThjNMUBN~e1rBq7I|B?U+TSs<=#62ehc^iYmXl&_xMPJ-?~4! zE<$XFeJ@e3%(f-h>BL?cfY9{)tl?3N`EjsaoR|-Gz>bN#g1gnwKl;Ld68gqu^o@b= zn*#d3sNaC@hILHOgCa}1ZTABcI!2*3Lx6Yol{Tbsc6^OA{g4)-h zM$JoWokOk@-7I#BdeBh$6Vi$ddtuLyzR7jNGrC>B zdIU*c-B3_JdjwG)jq=^D??92f~`HFhDesW6v7#96D1T$aWFzrjq}m?CQIGij1W_|>rT%=Xzt0id9X0Dp@n l&M+ z%l7;TYzDAQPxQUXb(z4XNh#c$e=o`5HY=kkWg|lV7kO_U7R8nQ4_EaLqPE}y;!@o$ z+KNj98c8$>f|dd%s4=@q8Zf5CB}7dIx7Y|qW0DyJH7YSdF*C#@6IDyB9Ih{&&`7uIYS7gP1tP3}G?Y^>$m=*0NX)a$Ian!_MZ!vT;b!lTs8=ioI(y z*D~4zDKuzbYSFe1q`-bS@_4njTZ)NgLlOHE#k$%1uV%j5`MwL^4@d0ZDVF7KU02%` zJF(1VGb8q|T{)Mo%UBnwDGt}5)`FAuR+p_qsp`P^ub{aoAN`_3L0h5?2V#EOf%ZO+ z_InjDk2ZXVwLn=1N@dy=Xu~~>uI_Ef*|xHDTUku^HvDye_foz3<51r$Zq*1D_q+DJRDXy&A8uWPbp}1^`f3Yi z#SUdBD7g@jHP4507}Heqk;$~0cPN|NHQ--=zRF9VcT3|Rd!d0eIbCTEK;EZ*8H;&@ z`eh3G;Ry80QuN8|fqwaS;3UK?#oGBj;+{g>N*Jyua5K7a?=YMexCgp$I~cCHjhDtBXXA<0eJN&2s{72GEv)W;Y$NW> z-!7$rR?S@b28+AgW?fy&+VgxkjT>s0j8&wc=uo~!zNSE((>S7DaI%fon)bZTb#M(! zc?2otW4}bf%j~T(XbPs(U(f5L1K$E2>{~0BvK-z<4(E>jLp{EQW{R?Dx%Gd}>z-e- z=r0j*jwbA@cPOv6>A+n^^bV>E5BgUPFCD_$?yk2#`d{9Dj=kLzZ-=qBx8m&?U2nhj zzr3B$^>$zO_RDxXr0eaa|I6E!yWV~bZ(k_rEO*-f^0wx#w*tQH)Tvz1nZy(>GEr}5S8NAKpy{QTIj@MdbOsllD8u@+;+T>&@= zFt=P|eH!pffF}V~0Y`#HS}WpOO;Rr{;!%P{fTLSAR&Z%r;$%CNVXb%aXwL&TuvLdI z=-C%&JqQKNE!VRzJP9}$unL&I@EBlCs}5g4JihP<;FcERX7pC@ZrTn-#_gW5M>}VA zKQHrR%T`tAtp&%~YbW^?#f)!@xs$rbKdm9Z*FL#Z~0FQ3X6 zPAucB4(bcL36*I7tkxCh(?;S7aaRl$6ng^dVX&0AHAKrtpj!vNVB z6a;9vuvLvRhic}86Rp9ZGd!8f)uF6F=|3r_zE}pH^b-2xX7H7d<9{6b+2fYM(7y2g8YH>g6W>U)@XkUm< ze;uO^Sgm%iMc%pxDTlYv%E=WHPr?^kSMNqG@~FjuEtWOcSNn75<;_GbcGfE2RiB!! z`qXySr>?6$^Esl+BDo-4XA=70qHf5U*}(wynOtinwqNTzFXWEacLmv_qPV z570ro484$2?vhYL7_GOEW;k>RclYJ{F&<{3Z*Ra{{t%4;!22-Yh3<3z&S3TO5FN7qzL!cuI);(HjrX1 zrJ$L3DN+pdX1 z10#OTcLcz;Y->pa#b-pSl>7#U-~ZjXuU>Bkkfq4m>9Ypp zl1}U>VE^IU8;~ivqQzEYUAT#;vmxf3k5*m3G)ZwwY{t5QSbGK|?iAvJ1ivgvam3s9 z2mXk!Q~v10_5t=|U+FsJ<&D(1SWWi?uGEKl$$?xFsJ4TW(R(7=l^s4#I)7p_=GY&= zH;hN0Ttjm*_>f(gv#aoA;=Tm&(OPM!wq0@iN^?jz{o4SXgB^0xOz#cA*}jaGwv`%b zsD>*fPLo1>;q{fpSpSFO+#Kb?S=%B1XRNZV3Zz5-45VANrCT~4>1OycR@+tw(xI0I z(yiXuEu9AG#-kiBp77I}3tAoot)l|8t_{#;4bZwW01ph%`d}BW4>DRwSN0&I^+86f z;lI%8>P7?6THo=@v_9J{9nt#t4o-?VL3);nWlx}GzUlDKfR7?v-Qk}B=OFxL2M6sw z?c|~TktP%2hY&u|F|jNab7|>Hv_JBaD==E_&})H-gv*m)F35Y4(-I< z4_q;D-pt4@+`YhU=`cxd?d3is3DUcl#+Jy=BT%Ba9U`^=C>=)bok?jBo7M(R^N_08I(2>+!V=j{ML3Q z6=|RoxAje?_u7>tz%)|&5R5k_p%!{0{SsT}8?mU1B^5#7EwDqvZN?Lc`E?(3VHeSl zpF!WQ0FUuI^zCOb|LzBGvJi3qt?py5teGHu3e!K1n_gmn8 z1g^902)7rwe*ovNJHosN%s1`b>yGbMcRPNe?kd~;bywI`cYkQ7y8BJHy89SusO~le z>h68ORCgN!b+@~HVp-lDb%)z-(qE7Nx4NK}a~UYjMY%is5#g2s_p5GoLAWg7maw|e zSg9vr)f6*<%Vc!{9C{Mro&)a5cH+^gHV88hm|1t!g{E6wJo*cDac`h5(z@!x5x~q$ z?(7vK+NtCsO6%`OLj!e_7^sT@sEdR<>Y^9wBAMzUumaiH92yVm`1Y<WHPBppy^X{EKXEVMMRTGo;6+ysF4Gidtkhzz)M1v? z7g|>t3Nuz23-_)vfnN;*w;BxYzXy2#kizS$dlp*P^ePNbsgj?qpI9~^dGP*r<&SOk zwf_BpzL;m$Y1)>H zZQxsCTW$ceGJv_iEhm6^C4d><_F@3DEP#n_TTr`Ixig59((`Cm+Ov}6E}T;E zPPwU>LMv5p61CdHH?LZ(Fo6F;hU{dwboVF@RdH;U#GA3Ny=D>TzZw}1Sioy z^#tqcYbxdZEe>-p=Y&`J1rFLY9Gj72|J z9fdypIwW368;Mcu=cxtY)*`onP zGl=Buv4F-fh~#XCuvHy*hn#I@a(25iwB@O5G?x( zjDdN?*phhdcaYJ(M?ZZG^C9Uco&@|2`rq{&+saTK=GBbM9LuVKNwq5lc5;T#OviZF zRP{)@wu;t{2%pH#9c>1Hn*FcxmhwbjC!KPI>koEyJ9*BXa zhvSo=qu?mkfY=e>hwNrfmvEDJlCFnhhqGAY7TVjv_-{Vy{r_9Jr=i^1<_Ekz#!Rm9 z_Z^b@iL+J%Qa`~D0G8BJIupds9!>&$L-n6kqWya5SxV%Y@N_by=;|DWsVxWHO? z7TQBtkle!K-ey>#dFSc~-^jHM=^yml#mDw5>{lGQ^Nqx{4YNP!vupMsEly)t@r6%R zI*)AgOe_?+x1Cge($wOC zJGi3Io#Dmth3(2B+(W~OaK+rt?pxt3^CWijmQEU#6@veKLd08Q~H2Ufl?OIPVP^p&h;lHwV6yKd9&Jd7`FTV-Ks* z<81wGu~H6eOyGJT+{SKq#e3S6Exyn7THNBGP>+HhJ2?Bp)t@VSaJ!$gFU8G4zPA>? zn%C(bt> zfgI$;+UYnPA!>_t?<9F;N3>O_00v;Y#1P9{A8NHW%IOO4; zqQm7b?~z=k%xvR_>AZAzz6xhE`SEeCcM_FvwYaxE7`Hdcq6yhAtTw_|7VJA3U_CNI zjP>yBhFei$+qbyw%5Dkz)1Y5W4-xyj*5ih$NzAu$mL1}5by#+#{2DA&Rl&|=)j`f4 zTMe6+*}I{^D9PsHV8O*!n?2b!dF-c^9-K*<9JEjE<$fW%G?yFR&pS(`Tac&ZSL+?+ znJz9m1opB9a;PaUbQkxW%+7QrrQ2S2I{7$T?!(i5xXcN**E4gY>6XVvqMrU$+>(Ti z(WoBY)e9XW?pN4Wr?+O`D_+m}TshjxPx$!Y3odS)RAYNx5TA~;r_7r((sOfWMRx9<;NwBk#B32%(lsn`X-0!>p>D~uxl~&xB@!K0LNXK2>*kiC_ z`gvI`F|2*cwf?3_^OSP{bS_k5MrkOgz4iEj5pJ@ch_n;la`Lgdn4@?% ziQbLNOW-H!Zf!KKay^o;8aH|9-lz#ZtJkrlMK(`b!@7)J&ZI?pZ{DKR0F<|AhpW1d z=i*`05qJIYXhqz5_41CYgHM}UYqF>Ja3wV)#Px8RTs>S|LxRJ`Al!+GnE^{ixam9H zba=|5pz_>B7LOaZtbXwE0&XFRCfo~>re9SB_s~s2yUpV3Vqe_YxmTo{+b3nUX}x#@ zeJZTQNLGv|U5+@^s>shJWe&L<@m#`yn?bmDPIsV=_#Ez8NPn{_W|P3)Me9yKDPQ`- zER;^#n2p1B(ws4a0^sPdkaoddi~xj^u;aep6_kHkq~@U zoe3*=LtE%BH7Biv-6XHIQvSMr7p%7VPd@GtgT>Rh+bm$7eN+l5u97*&hnYpGT1&K( zvu;owI7u|V#4c7TeLGB6J?=mAJ1gZkWzM!i9pT`L|DEw+#<4ozgMBNX7Qe!c>92Zk zsyulsDCjh-a8;m&-&e)#(^#o?t1}Q@>^!ZOI6{iwSGN{$(bKB;FA8&gYt&t|LH{4- z1myg15%um}=#^i}y`_Yv$=V%>p*1(MzLdiyy*;R!LSd50u4AEIQixq!)A`Pai(qqA zAKG)E=PB4L>#gCvXwhY-)vpBDxNY!;7KUt453{gSGpFYU^{5c((n<--BYSO7k2#KF z9)GAh3lv@Iq6m<4QGlWwS!d-hl-m@YmH(>vDLN~EsrV^6E1y<~qRw{~{TGT(38&RF z-KhG5KfJ6kXoLF4ZWJErMq#-l12=*BQKw;T_O$wuBfMs>>tLhiMJ?<@Oy)NyYHA?+ z!Y&>xBPAjYzEI}47)W~&;nT1xC5UI``6$Ck)T#-$2hYk&6alNsS$UzNvG>NBc2=H? z`0PevQXqC#1v4hm^6@u2XkLkkK&m)~gMqR75^ z2keNLao6`t*-^*Ac2zJ+`H!Y5oe|u^S^23Z&K^=J2nm?81w1q#>BQk#K_BSGF37@K z#C=t1XvpbrXps7Exnb435<)tLRBw!GFB#gB*LHmxe`}LbTk|#~f&6JYW?|wvI(6vf zMop+Tz!oeQHP)NCP!O%r!LZ}_l))IVBYjq$2kY2aVZr^SHGGwER^Hd7hrP$nluvg{ zIlU`oLj8QC{7qBPtxeiT)F=l(LF>GA@KEB{=hYmV>&m8i&eJVHX=A4)M6yousXHl4 zbIZ_A+n_#~b~9om><>)lALvoejd;&1h&!g!{P3<@`GL0{O?Xr_PaX*SCWY?Xv~;JM z@1iBG;S^{|ZZbOiHHVD0diYTh)qL#BHB$rS4Pq8I4XnIp<$p4(I8@q%`eAr)Ow*&P zX|mS&Ot;#3vRj$IzAJsdrp$$I)FN8&u6jIjS4xiMtZ{`Ujp>$m_xgPAt~Y+bjn~_G zcc)_WT`A8sg6h#)m+huT3;xT&PfVM(t|9Xi^Zne|bq$YvLaQlk6CK{2jCEb8l(W#k zI4LHV6Lut5%9%}XCu24S{@JFj$+!)S(34I5B<^`m`pAt{CX};;p-+6K48Sg_frZZ^ z?Ju{)5OTpqGw9 z{HnXC{Jep+fy5g+%a_;f&CZ&kHhAW)H{ZvbXal_2*#;UfwSm8UI%^P{C%90u==Ygo zWaXnB9I|b2R-Sp7`0-gEYdNvL;E|n)G~)$TC)bDDb|xCDJ&oJbLMn&aAOm_wfk&Tg z(_4IKzt6A}i(aSk_q5NHP<4oKQXT~xsRqnRoQ85YCw!(Dj*xEwZI+m&i@rS{ZaAP5 zUkTx&CV9;kmpC*fT09}^UViM?giAU} zdgYa#chX7r2Z_!T4Y%q14=f4ZrnCFkH+FqJt>Mq;#ebE%)7gDyS=N;@p?)4x9+mH= zbAIrhbn;i5dNCRwd!<(=jYC*nJ{zEMaW@*@xr4^;U!KtQ<+O$`@#VF5(Ad4!g|3td z^>dNZ#b`X7_*o6r;_ebG7hq13ISbiU13gVEQ#B$tHnoN?(!w^(y}-soBH*^eMj8AnjA=81qn%iN zd*0}*2O3u%`OX=qxnAR{JpNX1 zbZ*D|GIz!a`H{v#jKsIdX9#GcnuvylH=^rWD>sId^4ySUl@!<`GoTH~=xd8Rmao)UBK2cZk{Y-;!en+Fa*+jTttBjh;HS}V z?p_J#y94hkX$HPZbv0pASi-@abrXK-Q^@i66BUU!_0tA-tFO*kkaAJ#@2v9&>-A24 zIBZ0sJ#t~2K~LI=JosqA7@dbXYQ=|It^v=pCOy{*eJjUx40QqT#Y25=r})MJ&Soq! z6$KS(v!=6I$JmfFz}O%SAgi>PCurp!%%*ZNr}A_0Wt}%Fg;3kdE_JXWU3wwy#uv z-F8Zyr{%rCX#M;~8cV@h@>N$H&BSYwVm?dZ(o$YEQbFnqSvwMcle)E1h_XbL)|pH@ zDtCy+2KDg=gH5+in{L-h_xaFQce}lb2b^9P4qlGGU+cV`zH>}c|M;O>`qM~1uI>qN zpk?@)*2#_es%E;^WYLtp$Y#A-nG-Z<$+|kf{ZXRZ(q_wYiy_g*s|R2&MtAPy!L*xZ zd(utQjN9MqK7K#x_C2Cck-E><-Al5oTS}trI(a{F^Ajo(4}-6W5mQr!qJ5rh;i4V@ zjWa-@rtE~gB|zhQb-9>{9KSFVQK=Vq%bTe9^bRVz)BAW=N9=uk$A*swj*-KkV z&qoxU07beF^!uxnf41n}n**DDG0@D$0I#@#fTyd-VUAkg!)a2@c7_HcC zzKdffu4QPq?+pTFFGxt))u+3+T<~2f=SccujSJFE9CsAjE zWh2wElHI6&7?)?D5AgftIxF{v4Id5G0h(3bgLU2*jK?bF_ss!Y@Zirn4#tBwfkm0< zF*Qk85rVItyh9dzjL~v?{y!t{R{mR?By`bDE5#XklLC1Jr<$YT-DULE&fL3~bj1J2 zed!&!cdz+Acjf*ha>uH|a`$Wh;t!L(H{366B^^Eo%K);ELS&QJr{tEyRx9eLCpdu^ zZ~{FgvaU;`_<@#@;>m+#ol?u@KHjRgRVnGMWRdoS+^oz9q#MQ31tDFPG6%6%#NOD9%1+eLipFP21`Cds5}>sa+O)=*Kz3AS>TPV`1iMEQ1rsC+P>Wn&&b(KLhjy{ ze{9mYLUH@=5pV;v3e%`~CNL__$WL@h)Cu*A(Vitu&@m)wog|rj4qK(Sd;9G+JtNKk0r7xqHNO)-&?(yHYQ0TB0Q{Mr4E5FoUek!b3#ke8H6j-)%zRsU&-< zuwf0`XlCKK^6Pf8scW{LkUx~3cM7mMZ}J>hdYs6fPSVD4rJ=*=^uj;VXUf6WOjk)G z=M>Vz!+BeY)AowFf_lwad8sr=s8TNaOz<-|$SOEb$QvZVrFZ(2t3DlkBay}?K7o@~ zl|KR9(cvtzbEKw);LX|6lzN`~r>jc&1GKMeVE>U1fdwir9~+TGgTWTN-GJ?hi7mngV>I2V!wo7FJb3Pq?Zn3Bkk1rodCts&LBD zsPa{BOnrQi!P`fLQ+vGK18>z%Jv8mJ^L(6ULZ9d(HP9`jRVnvX;{P`s?2Gk+m3$rM zp;L+jbsFu{i!RR>PUFK4Taq)*wb7|{`uXc;eG{-3qr&RrKn~t@OdNdH8B!x%lgjm} z5iW~IkKLPKaP!~zIB4Z5p6oD_J!bW=In^i*at#rWdum<9o}Lela_vg&U2{g>ta#B9 z4IP{<+G+I0i&3sKvRk2XbhBf$$c={Y2V0yIU#q12Xg_NC;SEc5;u24_`jvyj&c%84 zf}mZBy|kKyrDd=hhE)M;*%>*q5mM?0Q&iLa25})qCci&K`nhfQ4Fi|f;6pF`Yb(vK zXQ8jIUHY^Knsq^UYrW>2dcka6x&`gyTsjgOtu@TP-)D+dg`J?mu8Dk8A>;mF*G_tAiYyL-s?qarX&kGen^;0rMD@aXW6!x?l2#H^R~scu8OH zRNnH1s+*A3(6;;w)il8$yBV?Mm8e7cKT%8dRL|X;fIT=^F04}iB5;5nGhlvs!m)YW-sfh1Z07Q<}zFi(pAO zrD+`gd)HK{`Ee;tvDj1chhl6eGa=^zJGFjp9EIZ#lOGD5sLkvtj`Wzs-k4j18cQ+~ z%E`0Y30aGTCRJ=2Hy4|LY!N^J|j`>-ckJg>efgnG!=$eRK`UKeLZU()XA zP(EnZ?(ivp=+LI_h8HcWo5St;1CEL^%oExds8_+88QNF#4qDhTbwTce&lhMHm@7D2 z-hz`0v@eiVIKOWg)9#@6TCjUdv;7%4Mj@&5jQoQfY(G(iyZFB%)nU; zhYf3xH?!19U2S5>lZrPY1hw>#F#tRME*3?JmoNF4WnH}%+QsJ3hU=~YY*o0hTC#R zepw!AG(aCj*7^)s4HWFUYFMbgp`Rr6)*%L`PY`pnfwxRTeSpr`O63A1B+7}X=C+@a zXUiQ}9Ztx;LmX_AhCs&&+ZaCg!A<2CR5xcr52=^k2WK%z59pRmeFgRu;Ts}cG*>jB z{WU%GT+%`#e18UAdrYZ5GS?mmJ&ezF?EnJVO`8>xoj!2~^U17a74cQi(v*;lHHK9E-=F_MO3Mopg&9ux9?iyPrc!Dc! z9F;T{Hs>{$X!JkWk-1n9$p;|(-q}bdo9RHFv+omIl=5b3G19_scH^?_hd5ub_N^N; zII3exF$wP<1RZP82Jn*84tvwvNMa>R!=+0)lt|2A*)@947}tFd`{mWq9kDsws6_A* zVbKv+p{GlyepA^PmrQmfPsnrScH ze#l_}z8uEph5s;F*ry!ou#0BI1j{*~iRO@Nftc2I1H3)xyn{pyJa9lKiC)KS>%#BD zK8)$#p|AWAPYa&ic!nPCJyRpva*mao%eAo4iZddq5ra`O_}bJIX}1K;m|AasiCPkR zsSZ1QjFPV@I#HmVLAH#?{|JAr|I%_aUxZ*yqP}FL9+bTaHeIo2`fjh?Rmvvp$Di?p z6yM7v^;BqfxDw5FE%s+WW8T?l_FvgLSu}bLo_pYL#_gn*f&Y|Qoz#=<<<}0RH5|_- z-d2YlY|`i)UsfTT8+xV=cXCDWnia(tIb0#hAt^RdvrW5=WPDCK*5N2mYuKK7N_EEM ztMhrzI~sLDd%XRyfiUHsTyEH*ja=#eO&EJRah6Bx(kJ6O3p~CgVVsht7F@tF%y^ZQ zhWM>;@C8FbLkVaIw^l%J8RaZ5J^HFw`a|g?ChyhhgRw z%rPFDizstQob3!wmB8m>-5^t@Yj@($m#NI#TDW0UztBzPa#8g-?^O3-E;svuT<#3& z`IdbX_Hl^bA=O$}??6rex;+Xs_VkX-8X3r)NAA%XH(>J|dbk$;oqz8t4gtA?4lR6 zkZzW2fA9Uh7VEEG+=xDU3GzjaL}i>-J*9qA+-dC4AJLbn4*02Zs}p0m#_Hu&YJ7|- zu1cK@k63OsE~d;ii1nXya-mY`Sjj#@21|2>C&=u>I}9}aESK6PpgNryh=1!isAh!vizEZ>;R z-TSLt&I{U|hc|N1|C-~d9JO0$9ny(aFPgx=uIRw23C`p(NS6`9dIa1MpOeKUz=zI0 zhAHYOahW{4v>LORf6QztCw-eyeCxoc!e;0e2a5yVty1!usa`ng1FQ~Q56(hEZ+UZ%4^OEd9T+9@1%{$r<_|}JU3SbE@S|ZWflk=1+X`=L?*DTy-X-uROIh+owcz zU}obShbZ=PJA62C9Kr^v72$lY8Z$Zk54U??DDz~x`X%S7-)Hwr)oiC#O}kyUUBBJ# z3T0z)4t#`|XIR9~uzyG=4U+NR2-dFt^J?3+<#P9bqU93tIF4*$K0Hj|55C@&%k}-k zM(*17Ty8qzD)3Kyt|pbod9`E8Y}n5kZ{#>FyvHqv<*HqdiQxFacFf>Rzm$3bBYoN0#Sz)3~QdMw-~${2~Ju1Xl~{5 zfct2(ikkJ7zN30v@yFx5Q&ti1DF+W?HN8<&`vZAp`*$Dec_ZPK?VRj`%yJ4o-!7=S z(2?+XbWUz!7+vfIb;bDeYTrKhGVCq*j$bjJc-y{~3+nhVe_Ag~J3j7$I=P=8^EZZ> zJmG?RC4l)0!(0L8(*gc8ry1tciDsNaLr;Zo=l$R`Tn53Tm)>tCdR+HhP)m5hW0cOe z6I=rN3IOxcNCp=Go(fnaJqJ1N6h__!^$Eb=$oJO~`~+YJi`TXi>;OET!FyDK#{-UM zFyBIOd;`O* z{=)Kd1I__#lnyewasY2)?+;|}Zvy-#d;c%2v~L1->FE8(SnavSUr-k_xPZZn0cSJV z%JR-H)&L&H${Eb!hao>Z%YQ1P%MLgP z^`e))Vd-;FFV%X%6CySJo${+jpB9i`v+@-Co^X$UUe-x}IifI~X;HI|PZ~73+U6=! z*9gI*G?y+yR~zL$uU?te7u;rr{Kv+y&K7JX%+^x?))NVfvER zcK#)TbYj>t`k#`#UftrLkX>A_7CI{A6^#i81xU)1lPlz<2q(dsVy{bdatb|j7;K+= zHFg6F^T>;EVasAc|M08|`LV{=@O{Q>`^E-vGlA1H+#A@T!VF}|QwbIi#nx3|P-lFK>8jrflLDu>Y zHLib=zY-3=43Y55@N1+ngR*a6r~dnBP0aw?dQ}%=gBSM|b1=6$inEF!hx%tvV-2Wi z)>%xWG*<>-=G0j*Cs+I-1iBs6)t~V1#y`zQgOc6Em)g$BZW;3;pM9vr6&~Okeg%w9 zV+W>R0J9XB@meot$UXtg^T15j?*OJ(05cDmEBaZO6-r#ez@3vH0S10(9grY#Zi}mo ziC@oc@a1wp{hZ6ywd8WSvFo{eC*thsVV@OxcW_vl!}8TiE3}9_YmedDSN5qh`py@$ zmVDKr&sP_W&sQ_%*RYm>pVWSRmhDqh=I&Ex;&~X)EIf1Y%*FECs%#M zF(cCg3;MZgqQm0KRg>87MJI));x}InMf$J|%(4q|)q9;**LtdR&fZx>0^X{U{dapbd|xBOQ-S z>xVH>7MnEnnMM5l&t(2o9uD1my!E)8gVpjQ%}CK50sWBtQX}bxrH!x+6=bT5H_>cx z#IbW)&1Jv;3u$BLzY4F5@HOrlEtjC)w$}cM|L9J)MA4+(h+e zu@5|*ZV`1Z_<-hv;hYju3KPUhp#CFkypX8c+@RFTwQ7Z=MSNURrvIcJQE#Y= z=ihr~N5s%$$>LB@+XC9lVncSm8(}K`LKR95Wds$+i_0^Di{*?S#c`S76ecFA6U^FM zr!_r`A8{^6e#?RVC^kura#K0^3BAN^iPfO8A4f2#oMLo^VDD)Me10C#z;6R2v3C-C zRD;iBl2{)vH2UeiJdSkU`zNF@6uWOY_><86;{Dt}KDm8`N~K>LXTMR?_(RxX^2opy zVHd|0k>XRn_VMBq$7sIRTKlK!rRSUBpP0cKYZ%~X0AE7u<>>TQGvG%7?_jXO+7s|Y zfS+Kn$r=oJ8vKCb1T}g%ofoJ7K@}JG=5k}cgupdsJ-2e)dhRof*>;Rqjmv!a9F@z~ z%d2zkfnO|sVGmCP%JR8-Ahc3BfxRAcg_f1|KQ+|W<_f>pToZK7hLl}TZBEozYvK+y zzPV1R={%_pKlYfDPZxxppCb)Jj!D`(9@{(p{b?Ygtt0ci}%f*hH^fh?*YAlPKQ~+2njZ;sd9SMGe z#qS1e=LvodutE9>?+;^eE?}MXSH!Pj`K@8_7@Q?|lfl1Y@RkLv*myxcwZWuX}#R_c* zq&y$?i=^;2N>K`$T&xU}kdHz7C*Z{lp1|Pc&G4nh;BkO?X#(ULY~`VhBXfU?ZxD~m zOTS0WI9N#qmTDeKKAyn?8T;gUsw*<=nTY<{)FXX$4 z;Wr|kR$75{M;M$7STCuFKLdC*G^`rwCwz4uzWNFv9W)W(D-ah_`HH{^OT5s(WoLO4 z>c^O0K=|$K`3R3Qrz5;0`&ooz%uge{Gy4gIr<4Ab3-RA$aqjLL`3wC4_rZh5p{BgudRVg;4Lag4z3= z0Q*)#i1&FR*!zND@-7w(-lYQk

(@GJ*3h7f1`rRnqwd>WRN~{}XZ^Ntn<=8K8w4 zZUMhlBU_rFR{{@yK{bb6g-)14U-i9;GY%9A2QC=5Q-*0xkPsRmORUk5ERo}v1!6~J zl`rfAN#80JUFD)G(jha&KKUeJIBEX3x(ULVMy&Spc&+pa^e;Z;Y2;vnG{8$qOj7}(Fv35bBVbLhZW9;>3cJ~@pb5GrgOq~)?V1g#5GBCrDJH$RA+g`k%>euwgKvN_ z6~uJc4LPX^>zsTMlr;wuq7M?p9rb zvEZtjQzD2#TXu-1!mFzLK*-jfTYGJ-P>#0Dz)t3%U4x5B%N#8IwL>pLGi58NgH^ZlLId2Oo(usR(d+wOw*`It|ep<16=nPne@@DhU7I*W|Vn{Vb zQ^b({shIU#xaCPLUYe(O_1Y!EEAMI5E0E;kvz%5h;fBr?$9mOiPR!zLpQjsl^(d@7&F1A%s?BV zeljjEbh;vz>S9%84ZJ|pd^t0Z_B5`*|1Q?gopjq#FWtgebn&M0-nRa=t8lmQts9%T zm8q+sD_oVjis=e9Z)@N7DPvnr9!M#*rs6@nNXs<17*>X`M-sG?JW!L@T8%WlC8U79 z6P{;--i$2p?NjZBPu1V^XO!Qy`{jgS$6V-vgFmok2+)MNaPRc~n&4t1^^%x-#oqe` z(AO-{dD9AYGW>g9fxm3SxVjqbu`EBW{@XFic3M5|h{bP};~raD!`ckoM2KB!!yh1p3JfA_pvjbujWs@h&S@#M=PJbo7SMqKA}8{a=SIA^1ilR*MY$v z)^VAan8c*!YtSP@b+J?6+m%AIahv;%mvH|tTB@P@EkzFEO0FsJ;3@Ik26Zmyhs)I} zxeD;39PRoWq}N-blP_YF9GC4)7cpiM>X*(g$});?U`IG~5oAc*8hWax26Eqz(V-ZV zE8sjSPff-+S}`7+TI^Hv=L25FU|MS&!js-ZjjylkbLmjyrggEG8l#Pu8luOZ`#ySf z_0Q3xs=tXIfnBkU%lYVOmuyJ6Yu$izhZ=XR8+<9Den2R8q;Y2K0A$42j4{T4KE0kB zYZ2{6L+_QGG==(>vCzh#d36 z?{cmwt`_K}?jd{8dDv^bwoq88i_xN1ZCOaSk6PfxmM_%=PS^OaRl>sAV!J%5(O|U? zo-H0#*0xfcc$J@hC-u1B<~pe+Y{^sa-{S9$&bIEo5&lOrI^e(ER32_Cx@O7hZA+;4 z#qLo}F?-Zt3*QKTiFIun;$8%tf;_Lb2`5z*k0hK|Im=14fo_bA;%j*8Q!g8FlaB7f zLfS)5Nn<_5t9;}$H*ijy%TNtIQ_y&*HD`k#$1i7rAG<*@S7ok=v(Wr56kM0@tLLoi zY(aJ4J&O2(Ffj;T1G3^0+Ud{;SMWsu?SUPdOPFbI<0I?n`6Y-8@WiS9(tmW^c!&RjdD8IYW5`5{}k8eHQ-*E6E_Pp9NTcqkcY3q1S>EY zi5bF0b(165I?$cgFn8Hg?u*z-=ZBxN4sk!_Cavbr^8J#@LsIpp>gm{|hN?%Bq#@dU z2>V+u)K`UD9@Hav>#h~_@3Vfl0%@&j^*)>=2WA+hK9|Fff?lM7%d|-$+DKhw2w{E0 zHMo0{ubzU;eiF~;*uS|f_p0OJYm`Dkb+#;wvG`MJ_chm zUXS}8m6O2>q~VDXzmabdHp5Td$&P!Cnv1k+B*eBD=-xYr_r7a9X6yyegd9e~LyqfN z^h>3)!QNLVWv?3jssE$A?u$nW{qg3m_-)WXl;VC}lH(1}0Lh6PwnjVge()#2IDjD{jj$|Uds4}E(i9XRu*h1AM3lPum@ zF?Q=r$5G{Gb6=qfXKCSG*GO>>C53rE#C|jR;r;OW?_~}4sj*(GX52$=$<$*V)<|D< zgrn_imWLGCyf&AROnks``Ldkt(Td^Bf8IdPpybW-W*e1@ICY3~C0cNQiwz|%&Qc>! zs3$$pj)~++ctAC0gSUD|n78K+!E*wqr#V~CqFzOG&)%mjZlyH3>X2e?7^UL8^U!jB zZ^{m=W4tt^zQmCY<;xD<3Hivg+!3aK~hCgJWTg%eddGl&dz;xc}Q#`{(f!f|I^m#>WjB(}bN{ zD%po@|D_jpmAT4$L-M!~(6jjSjoiY=;BOb?%*=F)EJ(@A&r< zLr|Li^~7sDh`PlM01M3@LW*4!QZ>>^=mMP1*vmswvG-(n>qa=Iw^*!$AT9k`jXxII z4Li&l4s4$4Egz7IQ$n!Rpe@i9=nMKK+g<&zuLNtazU=Zaw!>%@N#vUs7#C zc@kN9T&z5OS$QU)JQGl!r&)QPy&RVc+2AEA&mt?8%mLb?aAsq6&A3!O?um5bM*|-L z{Ir^Ayivg3Sj^tABPIkf@ioJ{VqRo1Hhc%JMD5Wv*3@8@*HVTb3cL*b&>C(VeKXjy z)EbFgzJ<@pfp^py`bu&*tFt#d63TIl9&`TzNCP_bX4+d7#1l%NR&JQ`L+KMdmxrf$ zAnFPK-{M~%k;g?u=5bT-zXAWb`1j!dWBh*|p2vNQ|0>kmc+?;1eQ%#hfZq(P7o?#$ zpp;F`JpS#Us;+zg9pgQ-t=n+Ou`A}b9P#QllHhD!PuZWqyFSzH82Y`0H2oN z_X^z)cl8}gQ({d;oW$bt-N|>vowACEyN%^gXArB(NlU_8?6`ABBdb69j?>u_Bg+m= z3Ap3r!Dw-uT48&!9m;Ro{r;;H*m$7xBsHV+xX+^VxOV*ig#Y*PzX$&nqktQc$Nh-^ zk@h@p3;wSHo;EU%dkN1q;F`zfaeW+l+-$t_=otLtd3kIex8~$Vj@nPKC0N}zLbxjQ zv(Gc!*2K(k>-tR1e9iNNt)D;N$GZM`y_IyCX$?|(k72qf%>sm$nMOeKwjkFzHQj8< zPv4Ni4-1M)llq3NUyvq^FlixgeCqhjsZBqbuFIH`QKcR+PhD_oe$w+BUZ_$XRe#F- zVu9g>M12;V^XduJ7V za#w*bBTXyqRMS~Xomj1!wY0W4*$$)`JG|ixeuBZ_fOSTP#|B^KCzOX7PKVvLGEF#e zJ%F1Ep7bLP7X_YZjvcs2;O>Le`q3Q7uo@GfIHZWzQVQ3caKO=sjeq2VszRncp$ubr zs*q`qu+)Q^xu{G?)cLXJRWD9MoPb4S-30TP25`{%EJY9Eg0Wk7LNTy+S75j9D+YHk zdH5^9;gHu)C`}9wpAe7z=Mb^Rb7moZ{}!;dkoq@ql;(SuW)ryaHyM0|!Eb_#^Un+y zj+mLp?zDzav-{&l(;JFjEb+AAR`hGijr1H3`7{1o2RJxbidn0iMy__xDa8H?VdRLl zkLLMGADxwDyAM;~J$Ja)g_g=7Ex!&c>=Q|q@^cDm5c;^s*dF2$&dpWIj{^6RhWL)g zxNXqXXz-0x;B-ckmAAW5qZtCeH3c{q(xo-Lx;z)@3XyIiaPeAtw?6Jyz`YCH7~odu z2-h69#OoFoWL3&Gn2sjsv>3HbaS!0V`N*pQxO|P|;p)EELIW1dHGaRGYmCl@7A_W=HqCHR zS7$cbT;Hhq>n|_FsaP(7uav)SI)ktfxIYvIK;`L721d%5Y{?DAm~c&CGzjg?-=(pN-@>lGq+nm&A z;uD}Xsf@>tjXcGG)3R;i|m_dz@3 zgRNb`8ICl!P=YbuDYk(rZuAkGE7YZPp2Rp$YY0Y3lbdkf*~2w%&h}=EruJ`gW;n_< z(7M&fUH>7WUXJ_64JPZNpqqf!osrx5e24r~NvVnUI@k z{8T98E6o)%4rw{JS`|j;s-?pl!BzTDg9-II#9MrR&Cdll2dfLZ#Dw8T<*$_}XTEwZ z^SDr<^no5?7SmH7MT+Crqw)y_Jk+wx<)zDOmzS>Cs$PqOmxAbjt=LgnyTS+F+3x6J zv#!WkVO@TGnI0#G^VPq{ksLC@oDa)!d&V4kS9ANte?a9>}gx3LzQXK5Ra^W# zW~wEbFS4XsQ?xj}rU|U7-#4q}LsGHVx{UTHXotcoM&bmO(bAz19afF>hvfHbtEL`X*z`kyzM~icc)pB#a&6SQ5qSf+Z*bT}| zFTqL43gvI@!Xo-V-|oe_QK9@5XJl&AZ};)<0;lsTl+P>76-Qs#gg$OJQy=%AuZ>6V zJ=pH=-CNOjF6E3qcU?@ToxAkqt;;5)Hz1^EGL7NK*J+i4WBGrM`i%5+?AB;#H=exbDwlbuhdKYnjT;*Gjf@j0?Bc8K(UjKmSo_`Fy z{k%M`8g1=)JddL~r(IO+DX&OqYRx>E>z}gE0lj@ zSI$2({cxOk{*76i0`gQgTI4%sjqiT6NH$vJ^~Pvdlrz&Aj+n38gaw>^G-ARLvj+Fj zD&PyryC59)faU|UyfG{_EO6d8G&L+mQxuk}#iPTcFLE;Zc#!IZUOaPs>3aVu`90vy zwK#=Ka-d%xEa{R5FV4^7hMn5TMY!@fqA}uQo*Q&n%Z)cIDdCP8zP@!ZU&#u_=$R>8~c`{a_ zhVj88^tNi1bAvw|kK4sB!~U4~5lT3xjZTGP(nkON$jV`E_BD*n9u1xHFt=Tl>Y|IfyF&7v-9s(ysgkvIXScnzwFPxW$-X zW5vW&oiql%?aN-sxJE+3q`%~#87)iL$hcJog14tqd)!f?+9}Bri zBkcx$3V2MClsIb~lVtL+M?5ire0P8(3FSZg%HWVhG@n0;1^Do8*-wRp=Z zO_gPgbr{1u+d^j$)))$au`o=Z=2_*JpcxvHd<^y@Y4jGf%5wC2E%t|eN-xGQ2F`s~ z{*(<_=#4zC5&soOcuqpU*!CJ^AGG02^ocEpaqBQAkE`?W9KR}$+qMbg1o12JzX$)j zH|B8{@ucI40B+1?q&doS|5-q1@NpyPQJwg*$CRuQEmHGUBSyU7YFDywFQP)3%XZCl z;Gwz7mpREiECJA|rK47$6 z%tRh3IghBif3tkr?#yR%w|qi=F`vYny)=~9OUP>$(X;Zu<(0DXHckKMyke2p{m5(c zf6eR5|JQl(_n2YR>G@9}om;TmK1;BW{Yl%eoMPj+n#-lx6rr<7D-d{7vBu@ z)f^oUzKG=VFMPtWpWv#IJ!Pi=QTr_=Iow=W+MriO1cR8PLNtmgccO^yJ<=&Qb>1 z{=+=(pTK#+D^UN+K0HKx<-20fOC^1AdT}rHf6rnNa66XS+NGHk?d*lP6qd?_ z&^Cm&v-E_c^w?A89hlP-X#TGUWO2imDgBRh&1U~a^cxfF`i}iqS_i&FFlT*={cEk? zxkc;1++gcdxzNkw|GQkQXH56x1;5dY-G69TjHmpXk<6equKpr&xnPM%(bbu>it<9U1A3WZ zh8vdtz=QzvY_mc1GQA9OoPAP4F>@ARhI2amTsAWvoEJ+D^HA{#wqn?MlDrqk`eSoW_8{A;mGL3qe-FLj38FZt6X)bo8P zMEpYaYa2QDVj+I0U4O}Ki)-N|+Is|V02)4f@qqd;?p|)rI^^+1_y0D$2OrPd`(A>L z8YdSVWbb_`2j>GMuD~9ANei1mL3Z4c6L>-A4adzdUf{f(5Q6>4@29+(*so@9t zz5Gb+r3b--(TT5w`Vj2(8F2>Hf`47jtN@4;fLw9QRxK(QsgK^97sQge}=B6P@(MuM%cNnx6ZJWqKiw*ljTmK*S-aJ04BI_Tn z+gmydSy%%^>7)q+0@_)Cpdf*Uh7c8SMO5fcC!`y)G)dUhd2ApHDvl9wL{J9_D$6(~ z$da%~R1_SSCs7$8xI`I89Q2tE9k@4S>Gyl;-tGis@cq5d=l#5YyauXkxphySI=9wS z=bSQ89~ijq*(ut_2iIv6Up#8Tnan~rwXX(fLkJlMy{{i&NBj1YWn9D1N|rz(Crn7I z3FD9rEni4sNs)1zi)5Mn20Wu3oQ-om@C3XL9dKbo9nLi9rww*&nr`A26hb`jo`J6G z7~QBASYDIqO)_g5XBqZ$KO0^vJR;sInX*_yaYGo7rAjWu@*3E%ah3>J-x>!!l7rr9 zz`)I%2;C(@l3?7?J;K=Z3;#}edCJd?<1k0M*-fa$RFNf^8)})(bVQ7lpm(KX3Dd#h zUgKuN2-Z*zYe)drC~;HGNoi`i6X%0&Rx4>L4}u?|KmUX}dKJ>gZeFWCzgiHIKXq?* z`^#%;q`bXRS}zfK7S67rcsSzU;WT>cSRu~k9^_)pCRbJA+(ok?^`LgIalhwQuTmM! zt4LaqwAHnW-Jm-`^M!Dr$t`t;Mk2bLw9h^9n`GK^L-(` zL)xOM2E0|wn#~sBqJ9Z`Huwcf?R#`CG;N@D_-q}?#*SA%3kihEHpjP8%xdkkC#4hp zW?OX6hVJ|XmQ^o{NuBa4?}B@zH2nvdH5_Jf!!4Ex3dHRkq8bpVH)(+77zN8Z?+;>6EYtr3#I+paOh6p2Kzx)# z)Bxg*P1@lpmf%hU2VpooUnb52Sinn z);Ww_=-&&g3ZubuJ1oX@RTaYGcNX|CqP{)ZL@BNtj?^~{>86K(wIa?uNfPp7Y$(#_l-@1AWN014)p_r@M0}pqBX)#BO0cO*5*_K6dJB+tV>r{cfR+p z-w>p_yJSuLO;e(e23cmKZFk~SLSGkVocDcY1|<8pLbBOq!psrX`g8{5Vg(9^wvx<- z+zPer@)`dyE<;6W$1rDpAhs!I{~@M(!Cx_060>~bPwo1;UdGYi6Q&n0&~G`;@>%R< z?_(FZZGohA@0k|D|Kl!wUAQs&dy~Zld_RXFAwBqo(6_+K*e5muPJ}V|`$ZXq%`vYt z1Df@W!f$(XGYmNts`GAyw!JkcG*NpRR@?!l8WIJw1si{7m)DAS#_-x~_s&OnEDyiz zeF))uczBcdY$5a|gn=X#rFs@?-YtvnOw>2-#kwXvao}lVzS*Nv8*}p(Hq^qf2Kr5jxU>*Z*?W@Pkd($KV6 zy&-h{pu9Jv1Qxb_UY=@4uk{3*^i;#wZ(bDqrwHV~(-66S(Bi1|arwR1XXW=vLFI{r6i+2d^kQZ#FNYTRX2%ZEY2 z7rl*}p-Vn@k>0lHshO+vs|Kx`yY9(VCsswo;iScMYV~Gtv&N$*tVU1hV=Qf^QS!3) z-b+)_x?e9m2wANu8EMPpaOwqPe*K=Npfs!Dq&X#=;)1kb`yB%ZQ^X76*Di- z6&a4*Of_a-;@=cqj;tAM?6;xcrU87WWk(&S)vO)!EkpbIDWjBi!u@htVCUgz{`K>w z)sDV=hu9(Rf=1oo8cmCV)q1C1JnN)z48pfvtm5HlgwtRZn$r6soP5#9!;uJ&!dOQ0 z_+haGQVXxWwU((JrhR8Hi_guksAj@Y)7#!*EySBnYfxjmkV$r%CDXwt01y z+0dGdMeaAifi%?dwZG0}dF%+KcH+Jb=|_2w-z{I#A%3Xvnh%RLeE%M@pLl0FC!K(m zz(!3Dw`*YIk~>&sLUJS-k~_)ZUPA9U!H|8=8M2WQhxW7)oZ>qgM`vn4)zO*SN@2q& z?ATTK9hITpFp5+57wA;n+Bh;G1LBT7LHtP1>@K$=p>ZM({C)8J$3R!ebO@(lEYTT@ zw(MpHVPA1PPQVJ89+Fz4S)DiZLaCJIDwW2&ek}hxazvvauJokUP`Dq$vpl8JBo@?s z5UYzxiZs*X$~UDo&zb=$wgqk#+?aCk2L`KHzZ+C+CF0c|R4}5&QwUeUJp*?D{o**B z343MO^2Oa14U!=$iJ#DX3VU;O!e~e`ItDq`|}8UPu%HuFG`@lO!qYAk-v#-@r0vp#SZ1`u5#HOS+rYzl`dk8=)%xU;n3*@A&Flilo3w;( zJToZJ2DGu&kW^!ygPofosYa4J#0%HP?uqM*)HgfR(R)cYt2!t1IaJCXezlaf9@z_i?MBk#hg}EwFG2?7uo#7} zw2_CxlvB6EVh~`mqfIxI^K*=)nQZtF>(WfEV{Nt0GQ>Kobt|keTu@GzPr1i~gR~Xj z>(8Fjb5^X+K9C-o>=XC-+*rY;3Z@!5eg7+uO%UjG{E+yiZ>r@`^W(50uW6Zz9Un5Zdn_JXzK|8_2Ln$L#QXCfa&#w@E zo+RY43s|fgxVYK+?38e<0G~<}phq3ts7eTG4B9ahw75R!-qWy2oK}o{V1sq z-e>W~8K=bO+JQCN=Em93sDgVDZY$jO*`-qJY=h-Xab4#ioD));#Tg-&933Rs(KGfKTocBI@fb6k)P z)`j!=t5>F~QUhB^>PnJum2Dw)h~qCuqJ7AciH9ItL6V8==qExM8|^E_UB0DELisP< zredalR@QUfljA920R(9$o{>EQvn7$PeXB{X5?w^*m#@?(AZGh-oQr-ckF~X?3t1BX8T%2 z{uR7kWv2H_z;=kQwh^7^G?#jlNukrjL1pX)xSY^3HV5uB!awyYW1a8^hL^E;eHojm zD`Q{7b;9)vE@MC7c^+ta%gfwm6!b{rAi=E5=n$jZ5b)G`dmA><;X)2b6 z_X!5^JastzN;5=27kd+GR?pA)(=a2X#npNXFMSEFdwT33aNP~+i#X%Q`50REA@NO| zZpY(JHH_u%*R9~nRt~e#i7~iziuAA%C$UT1KU zRe=uiWsHD_#I>E&M`SJBQxC3Xe;824NTiygOlD|CB5Rb z)foR^tZ8<9ihIc*v$V9?@rv_PuLt2OTa^PiV}CzXcM<$0D&^iz;$aiaaab!sq5=DD zlA*;OBt>i0;C#_dN5p(5&~&|Jq==?a0owGFAik3Y`DE;*dBhK&MF1>C8no zEZ!=_!kQCoJ`J3S76thipD46fPieNs!g`i0DcUciKfaD%QnW*SMA}r>TWQ4!n91IT zmN)avye!XT^@ziE8Cq~+2hC)M#MX{(nSvv?ma#gxowt;+kAH*=IqLN^;`wmzz!AOH z)~Ht+VKE2eKcwxAOZ@U4?c(=bsyq@c>~D}9pm+5(=>LaZ(}^}3!y%mMQ189B0V_0X z`h`ijuU4oW&Bqm-&w29Dx~4ZK^yq=lEtyCwGS31$xutRF6;Ec;IkD%iHrF9TAiW>t zL~cOp=WWq^MW@AS@*v(5Z&Lauoj4ERDe>r=vZU@r=*3fSjcNDOXg1LdDKE6kv;7u6 z+uwF%+9dS131#dP_!Hqj4L=@!%Wde3pwCMPKRmIF{Q>SY!bGpFSfRPWv72WjYE0~a zT^CN5v<}E$ASG2<10ND^2GvNambBZeUA=JLu?e| zU8v0^SvhY?pXRxUH(WRlxal>cOvkYzFd^mmg%wsSWZt0RRxCjB?P5xrg>Jj?iFJXF8#^?bYdonpi8koY0DVONhnCU`so@%+Q11V^0QT?HFqoq-* zj||$dcACagE%n~I=E>tv?%DHD)2fwh#6ykAcWBSQ%iL>q&G$;ll>;TA^1Er^<0q|} za_RF`Q)V^%IB=ZQyBaourQWl*O`SH)ICaox@1NJ}wXiD@a$YM;v4ortX5fd^>o(MS zd$;PgguxzNuu0XfO;WY%FVuSVtzXmAElJqH1T_bpw=k2WYKC@CxB+ z3m=`=s@SuAUI;lK%7kZ$7ZIAYeoqjzJ@xg>bLO(~Nt`027+2HTZa;pu+n=B9-oS#D zeeGO6CVFA>G67noqqYXY?l{?hU_O{-V3k+T~C zNjEm?_`p4Tx@oi;G*VxeMsDw~X|&Ay|AaX_v9drrheMrW;|H?@KAqM=@Dt zp8-R{w5m*f{vF7ZQl3HS-(%3dVb=Z97?ZswCUb;9JGQUm=={SY48+OL2UwfMoe{?L z8hyTz#Z$h!YeoqE9JG(~iQnVgFp}r_pT=;UZ>V6)vlp#$ARD6QvLWr_Nj^jRur8+= zl1?h9FF!jO>n*sXDOjh$r!fw9H=3z`U)i@$U)6@8AztYdU+wDIx4YI*-}blRgdT19 zW3=Is)P|ov{`CK@4X?)u&6REViI)Fe8!nWLPxCfh_Ukr$ZCaeVCM{N7(VsajrtAN_ z*`lGFWvy!5j1kt{M-oEIr-U@zP}4_J{k(sg@L4(T?xmYupPS-o+%+YrT^k*K`u+2& z;K`Pt_TUTp^FiS6MYlL&4AHiMGtr8Bx1{67;ae>G#SNVc@5O9a@%TRV2K^QdZgbIY z2*Y{kOOOG@Jw>~H;@iHUYIbDEKGg=@7Ubd2V(?6bXVpF}o{ifVpV=Tib{|$USiR6H zCc*MJ)*`T_i*|QQ;}EU`AI&CTnlvXJs}X8HD-Ojdsp*#{MQy_F0Cy~O8V*JKQ!m^c zwFB0AeB!ds6X2tf&BMp}ss!gJU2Y|1Qyg|*XuEg%(v*}PabY}Vn(wwFpWLouBkoW! z;X$n5?k{8e=9RH0;IBmdhPha?z&#B&F++v5YGjW(Xt9f8fCRn5j>@`F1t%@!N`jI0 zN=JH~K9H6ir$gHF9k(4>a#tA}5BD_OG`M@=M!;Q3AKG6LbfV8=*n4%;hn@(WKCX^# z`cP^zr%z5tH+?9TtQq;lc^xO}`YG5@sxFSsdS`XGKoOG8qIDbg#~mgmjN-mxs#OvvAsnv0jAV2)7DuC)^Uaar;7glv|B* zBRS0$D1Wdirj>2b!PcbXQtsWqknGw>mv|ryf|!EoXOUHIM6*c2m{q z;_)5$(nP1&E-Irwb`wgZ_`t5)jywQ7SHX=ZeBol@u3q>3pzPQWil4kqJg10*YRFCE zh7rR-*j$DN4^A+{;tqJ1h+#%p3U&+4bXSA{w@)P0tZ_806>e#ALz8L*|jiQaJ7d-FwFtAno)Csc-kf+3k~eHZQk zBl$1=8T0^1aK~DLW@>P5GWfE*FZf*97ks_GjGaRHE%2$VdPj84L2)|H`p<%oM=4uD zi3weX0XPv>P=zJjKjiEOKrybSUENJbxeiP$m2+K1=hSFlU& zdA`Z+Ou>$g#hw=5!Kq4+XTmpCJViiCt#2z*Qob?r6ctk5^cj#c@|&}T^p+Yaulbq_ zgFLa&?2q)YGqevmC|<;^@lE3WZQtQe6E>o)5qIDCPQs#5bWI5HT0PIT;amc{YFye3 z4&x4J1ZY}zumj$89y&isOFt-naU|`?hkq$!AN|$O2d+k4Kj3>==GlUkL^ZyA$)ynR z!ObR;?3!Vs6Zb3S_~Wg|@YZgeOm1Q<;qeBlv5D7v+_#C`S|V98Gdx6Ku2pMgCF&*SQ|72%$kZ%NXd>>?X;Zpx(hx5M58 zlEld!cFAPO#{E2WTSDRd}g#m*zY|d%B`yd93h#Hw(rknEaONSi-MET&R*Ik(>oh&Tm7Jl z5&h*hGrU2I^RWb2Zfq9^N&fS({ocKz|9ot}_phS=d~CmW2ksD(&&T$Aw~4S1jBni~ zUf?~1zU~iP-`!aQ`TCFjyb2R~%OjqQOWe+7DJOwvG?bTe5b-on*|3n#(M*>8(A|T^4y<|7N!otMxXn03 z;TVK(6Qg<9fN+|44s!sVpY_Fgj|#uqN;TOI&mimJm&G=p12m5E+;^JzN{~ACl$|!z zB^#@;a&pF0nIdel4Jx!-$cKmFcvz>VLN z`{_6JKs|o{dq4f&bbu||@BMH;{U#icbzAgk%~Qec*jf_`OYu7EG;2r(adu7ol+SN3 z{<2ub&l3)cNgc$kB79E%h;R9G1xr-Mt?vCbmz}Z7CjOknJ*0PD0KpR~-``TN^KD-FN$KY}nr7Gv=kuz*`YBv}4J^^d>B-QpD z`u<$>{bjHgWQd(PGhH$~c))wIRTxgKrr8GTlrC82G?^?@d5NUE{RqDP6dub!tQfIL zJT?QdJj5pQ*mT5l8WSwHAO;N@$nCO(hoSQj#ar9hnPbt~^1(AQ*zQ7W8xQ#=u6?nw zOUy#5)i(VKoif4m5=Qy0wh73a$RX0ZV;VnGgUa@x&bqWc7v?PeOY|7i`ryAPtmt>o9yHH z!`Fs7dmh=zuxHC{a*%SSYoM=iSm6aG(x~;$>kB!;L*>VNKtA#^5|C z{!gIa|8x-g4E)@PZXh`9-OA6xQyLN-S}S&_hBHnfWv=j%cJbIUg*{ zvYxdb6pvpv*v{4T&WMIa%s%myZ=5B(IUG{-k?t)6qgT3N?PEoY(K$oXu`Lhi$C@GK zde-r0+z7DPp_}=Yb+aN%E$jLacgh;BWe=37Ft;9qRmspM*vdTrj%Mh}ZBz73v!$d+ zW|$0pFq%L6Vg8hV&xj+rKAR6VY?@1181%fL3l(_;l9jN5uZdcK zbxZx=2EYx38w@u;d6o2}pcBlnObYQI}yO`lyH3a*$bIomkv(x*jk zsROcTTcsG}S&{6P9!aKC^^K`C|F5a}TuRWJK=lc*NwksM4^K!yNOMqxEH=(=kq>9{ z&0H3GL(Q7S4=xT(3~FqUN};)ZP>khyN};*k%np(i2i`zlzP1q1=fW?maZc9^NetY= zf@QOgIwerU|)VebZx7l39vDBjkMQVwRnwGir*V^U(THXysSx) z_{~m&&b5ts{@hiyST#EA=%B*Qh0M?d%eJ|8*y**q_-e;>q*_{(A_9kSi~23S<$$-3 zH^|a=#sS!>n-m=h&O{pU`g5Dsa-wE0a*oHYD;%<`2fQ^GzK}eylU3_|+e3Gz92B2v zn-2MC4=nAdiT9RX>#eB{f+VDx%NW+84OPJr&nX5x$3-bY7P>X0LGoBxVsZnOee%L; zOB~8>ys&y|NK0hMkjqbAo(;$gP(JCB9>803fWe@dX5@BVNQ12D8SxR=b92;~5U%y+ z;ikM9({x``jP{;$J*zFOc^k)XQrk0-q?wG=2XJCIV_GnBO-3#iVLQFnJEdCAJ6le{ z9V&jDaerG}FN+>`^_&rBwbk!QFz%RADurlDrIpDaA4Mn?AywKDALU1&IB$4Wtc#VV9JKSc5u<$3$r?VvV?~ z^o;m}w6-QW!(e%B@fi_Dk26fUa`=K&wYWOh-%6Smj?7?jq9B7MP-yrqriowQeT9;KlFRm>5$bbl}@D4Js>{uR@_KD1DuUY&8G|T1H+$6|&usOm+XdKRAqtmcDht4hL=JSv&9*Ua>suo8( znI{~p=Am~p&}95wuzn~0rG4AtK8~s>WV8HdQy;6g`E%)K!?r1d8sC$Co=wu(p;#Af znvPIvAB4VwZ9T{l^c@Izn;bvj7B7RP4mUzGL)sBRaeOX-g=I(rgL_@?2(c`~J<#uX zV=lQZ3>K?~J929dEj})JDx;lki~fN-cp#^rB%~b2?}_I0OXm!A&|yPAt)o3o63UG5 z)i={9a}J|bj)!s|m(FdK-!M83+m8cx0W!p%%Hh@usnhg*9?tgFkkM?k=WT$52u3eR zh(sGzqhFV9O42q)dxVIXqtJf4yFKgB;x^cB`-eCUSe!GxB{iG3@6oin?1MwvZD;q~ zisz>sZQ`4k+nujVi`2o82*s|>cI%?Zlv}d|(XV@ z9T$eGNX}R_I{IiI%j?o5QyS#&n#7g9gqk!#B$$XbIsga%!AYq4cY>K z;)hZBA9T@KgQubl?U&9Z$y(|%w1e-kfA5Bq+BF_u4bO`9l&Xz7-RF$=R(b=r?i;VWf#diDR#rEvoi>tEFFFu={m}kscoM+G3 zokwyzi=9VXRt6a<gp7nJUhH&Y=7)wy|r_o~^$D`k$z0@J3{=uqG z**N85qX%V>zUM#EX?`6#wo;0^Cpa@?CceLwVGiqudu8gxxv)7f6jm-^)f{WUFMZTU z*wMTgEz2{|y`te6_-4rjMT;-Gyeky4*t4|*;t~*ZfhPcKzS>f0?if0mFZ9H#n#7#0 z?a~Zw+L2ipOCB1aWz*oKeLFA;0?KR+-doYNJ)=xItf5h`NnFyk4Y4B_Z-XGc-z47K zwH~$t-`2dCAwR#PYYUzq<>PUaIJRq3#{1GSC3bTc8}_O+SF;g0QnC$L8#m#unDrU2 zVm={Qqq=IL$%AL9H(RDa;@@C-3N3tS*Y1J!d)7$9H2W~y2xIG`U&nZ_8rSQlpBsBM zugRFg@e;b;-BTv%hZ-zyymPtpRY|A$FVuqIdOQDs64Nw98;YOrd<11WNGq1d&vq_H zd{H2Nrn3a`fsEdF#?rwva}XrYOzqNm$B=Og~HHvQ6}B8qSB3_;ZNbdMf~4z7Uau8x(V)I zNFNUWApA(UuKrq9i0A5PExU;D`$)^g^LW&~N&Hubu?L1{I}8ejDm?oNG78(Jp_&+K z?XY)AX>WH#$}N2Cb4W{ktDi#O4?23|&4v)U4;}4@KOevT7~$k#jwgT zr&QWF=al0e?;l!HGob||oVBMweIK@85g5KrKYx%6a*DG9&Z z`R`tn3E^t~TWh)*;lup5-gFbfYx(an(`bZG@ZXP3qY!T3zh6M^;l9pD&aIp8^I+BE z6GJ*1xIYZ5pMPM6StHfo;}b{tVtIQ&nzc#X)P5sYg)B_|?$5SEQ%LQPC4*R6+85XiWR@6V(-CFmHkx}I}iT{Jm1|*&4OM~v0%7RxL1*9-*y$t3Bx|W zQNwy6tq)v3xPfp{aL?mAJOQ_6@djyBY)FkJjy0>}2IV#_Bz?0W@YYE}qz;zO|ck*L1hzV=ru3V@}sWFFFtFFbOvKPT`HbIPm|x{f$+& zaDJyD&OzffbPk$9C!xY~#HG?c*Cx*CN~=qTT}HYg$GF5Vu~sL3d3lsY{LwbHoRxf{ zW<&p{g3X3cYhMR=?K&q3mi;s~R?INMlNtTLW0))|c@q*+EBo;uu~PFz0u zKD_TN<*Wl`-u$*~@28s=!5VS~H)^g5R!%hZutVAgJ3KPa z`EQ&yk6{cWn0*XtHtOFMENVtMA9vg}!5oM8=OzFLeHY0Xl9tC0T!twPW5FkNv=-`( zcfUnj@BpWZ>b}6r%_aHoYq*)?1*{b5%~3N)L9VR>9LVY^2CD^_Rjmqxjh=+ept$c> zu?@q4rLbXG#&G(QiZw)(jJ36?(WulQZl)GBnA4foLlTV621nv_u~VGfbxM)S9LZ(D zI>moFyy}?`^O{1zBN%>w69Gy!4gKm0J_w%E|S5KeL?Gz)ice zoIMPe4f;@BC%|8FM>(_2Dra+UhmSn^%*cI%*OH9XdvpE$VHT$qjiKYX&O=|&>YsRD zmILf-IOzSCNc_{O4Z||^_=cEU(9Y?s*@&-b%u|B9(+RG^hMF3kA-D&uP6O1fhw za!J%qvA8SY&>+a>f>V*HhAsqYm_*}LfUJnNiO!B{rT(4J-ywU_gKE?x`yN$8Ka2R~ z(VlxxW2TIym07fB)@hjzF9doG^yh)|3-_S!z|DaZ?ki```^%XNG@!cB9JL8{bcw&L zhZO4Hy2zq#8!QaT7IoXikD)<8=SOwo-rBSyuUO03FX#ty-vjU5>)73!G{7$S|dl&IG`MyXM zXIvgvEEq%L&Mq?+*=@b6`RQ} zSz@gg`Ucc8AHgg?t93GVfKPZ547ITQx5{F$l1@M^ZXcRqS%e*80>;coJh*oX`C_bD zwjZq2nppfc8%g$R+%GNZi*=bkIRU@ANkaNtnu~p*a~Pd`OzN9_L#B2Z_K;a@!{AI6?pz+6IT-prgEM1hYBsTvpyRVq!+GB|oS!`5aLxF4`}_K~-})d1^e zxQ|ydfNx$aX5$>BR&n^A4bZE2shn-RT){?tp=K%XuVtNc)a-$m zX{^**JmCNQ1M4vfIyy4sPg`m4CnZ&(Uqr+9R-2e{xe6H3c%IdsfKqPaXD(^@3L{`4 zksT$NG@qJkeiY{^BYv$o7+;7nai7kiwRoLF@>Sy|L4vRrHqJDbNX%EaSoT3@p0qe3 zW7)6-%#fJbAv=umA2RY=ZDD6f^4e~j)jF=2^dLxcEk@YqUDrZ$KrL=wPQ@(Mh4P=M zDrYAj@SmT*=j>AxW7_BaV~adj*NT6~`8nyL4TUaRytCfPxGq|*lXTI9G4VFiM>{x& z^wHk4Haq;fXx~8>4XwfC;b-sBXhCn1i~ul?j@t)2pR!Fc%(s>*t4|!)(QI8?bAu=L zE6ik&kBkQUBxEK@SYRH<36J_rf6tMxthS)$W_&N7_yES&TJZ^fc6uA?@ZH{Wb_9;- zm{wB{yWTUD5xAD0|I@rlIOGEd()N?Fh!Mk(X7AD=Z8XxtfLU)~w$MiQ&PanXqHC+Q z7T@J7?C1%v1mHz$5yB%u}=X;Qkx#3>@J+8|ODZF`>)qtQBtzw1I&nXMr)soLSE0^}D6@H8?S2 zj!As{E8%?WLhu1gQv1eMN!gKAi-ciopnrW9cLu<>zOv{iabnwdi2WpvZzJ0Y=fqTB z6>d_zWA<78OV;X}#5~`cAla5a_2c=)1hHwA5jHML?wRjAD<0?+aK3m}tmr%kn@Ft);wa`_#~xK+b!HE2X+x6I@2eP#z=Cw$~+e{A~duyy7vkpMVq)vy325hsD6)t)9?M> zhdn!Z&ZZvkl6551DYj_^*+nY3=UmKwZ-ysR(8`YKvswPFWOj(_^JoW1dJ zIs5rbzuottXzf39>3qz&u|v_?x4^a^i>m@}FUNY;y4azKHQMyXs@2d%!0p6+S%-L- zbTF-Pn2G5Y$PV!{Sark7a(MzyoC&W#Ufhb67mY3kVXyaL(E%B$p7V4l=4o1?w}}Qx zUVUy*)>D z_I}()P%eFpHuDvG8PEUfrPQ<;KuSvUP zY}p^2l99fbOADS8i~4Zu`YqlQ(1QLwIHf|bJeq|{iV(@4~M_l0!c0){J49>4Gb z^cv~uP&|E6c^a!cb>ZnK{`3YseOh@sNO@|*Q&VUV zT2={{12+S%5&g9VPL1$txa|nfg&zlZ4BJ;dPSy<C~@JK~gNm;{^F_5S-YBv`wXSM!qi z1K+U{9-olhz|jkVaRm~9-ql=oz|t^0QwyzA`33+3*ZQH|%o5C&X}BAqr$(MJZU~-a z<4I!U4S^@=v1@TdLWj7*#}s{S1L^K!UDNKX#j2k6JN*Ou9g>3Ti_t|ATd=n8zG*@* zO5&|b9iQ(p-q;?lV6Q$1yOHoegfGB<7XC`OH!9Vv^Pvi+Kc!|=H>m^bex%blY^@2( z49Xb1HqJsjb4gsF?A~j|>DZaGqy4d08in^f;Mve#_@MW)2O4j0^~=QCVyGrgCuuSV zxdr2NYf4e8wWJ6)@>WL7gasllfjPT<>l7Dw8YIVxIew#hqh_OaBi6B&;F*c2+Zyar zXf<+>+ruOobt-S?{0jC2TpJvfE$=O(QTAcJ51$7)4(!0=us*Zu(W`4<2`d?UHIkC? ziT$BrX0T}l&`DP6IZd0KZ*&(jO&dk)< zeK!bw>#6*UJ&q@`wxl+8D*tAkVvZzhOV%R=y4KinJp|dfK75Agjjt%%MTo*zBtDBI zhIe*rOV)}nw2@Zn2uB6$1@}a51v|a4g8cx$2Cfs~mc{sX&I-0FuYyhOtY9Y4fxef2 z&m)OX2G)T^*oo8g<$3l6S@|~m0%yU(Li{*O*zbS8Q{Zq{Nj?VmD$c>)+4pp3YV6!>37f0FifS4 zhC2$ga|{F|FDE-h&XH}G{bja17GHdeVMcw#R34ELg~0_e?V+#21f_FQ$JZ4DrQ=!UDq-^Bo8j#b+DR4e{AG#b@8#7iQ-t1M`Wd74a*W%NC!VyF5M{o!fw!*c%h$8tpwqjS|@*JQhLn~TA*^5y|Jl@I418G)L zk@B0#x&C5D5ivzFx)WIGkKY`J~}3v==(#+#B?T+eZm`3Y8%lkX~AxUe{<ygUyrCym2L|s~v?_6Ln$&*pdSyAG$ z(HHiU-BwUiyd01HaaU1c_ELLEfh|90Vtg?xS+O8{Y01h3_LcU$oCPJ0qMTyKg81wO z^2e4NOHNTyce`M=Toa@A)gviudG=D5ANhhpXK_y6GGH#Zs!{RT@_$Ce^5=5dh`cz$Lb=M!M(suJ%^sr(gLPz>_QTJN{$-z!U1@oIEngTscL~LOwtgXQ88Dyr5h&&VK)i^Yg5sP7#d(D;v`LIvXkBva z35-GA{fNduX9;>W@9i#|$v-lh{Nti2i;s%b!u&;czy5y|lDlCVx?FcvF>Ymn1Y>fQ zF@z5Zwqa~C@EN=jDBU#{nfzAz`BCMEiyfs&OLa8=RFl`W6o z$(RK4{ojn<%5fDe%~v`SO?}<-TG0wS?oKR_pLKWAKwf{VNbu$@<3d~qQv>0>mO0?jd9G5a@T$w17oT}6#r!vG`nbpb6$F-NE2WU46)x&sNDfQ}i1MaIGu@cnKtC_R5{ag0 z>P{F2>6PNFWRtTXl{&b;KrGW1`iC&0l7DC`a@lQxX+>GG@-&R>3K4j!KTSdJiZq1; zSEMNv;Ay;nFUaGSq;OJ?aIzAXQN~nKkexL4S0ht)w!a>{mGG9zX~8E(XNld>qYY7O z0}+a{^ZXTFQDVzmSd_DblI3y9;a?SWx1Ouo4*#I}*-rnga&>dZ5R#p<%wGb=v%JDU zb4AdiZ0ClYWkC@fZ1 zcQ$J5@|d)=xTG+DnJuu4ymH+@FuGR_OP8W$ z|Ga+$W}zb6^1z3Zzgu9O@~=3r9_jq)3QE7q-?OvJtuCxjQF;PhAF^fD3qm=6p8wPNqsr?!@{(Pt(sEZZH6LnUfwn{udGoOlWI=?lq5LDULKlA& z0I*7>Tr@EG$tbV5Q%(Q-HFtonfd%FjbPc2i=o(0&MonEQ-X3q47grdud#is>zLte5aTyO23s>S1iXW-?QHtLiJ}eNiK1#f=;`dYh{)!(B z9~w?8fTZ!NAFF^7A@KLcV{}coQ&lLoM{D>(C z1mGFu*S{p9(O)|MW#W-{iTsSY`7aYED)B%~<#eJf{fQIn<@^c-y7S8jbjM``ke@z3 z{tWzAoY@Fg`;`Hv&eT^{2Ih!g*&lqVyAI5h+M zOQ#=k;^o`O$3%v1!~2nIc|PBa5|1meMqHqur<-S+=a}y@-)+9%{L;>4+I!3k%#+Ns%r~1; z&11}C&Ew2z=JDqK(`QT{KHY4#nl0w(<{9QBbFw+byvsb-{D66$d8hea^L=K!*==5B zUTw}c=a?6oOU$|Et>#zE+suD8ziF;E?>7I%{D%3g`5)#V%-@?E%#G&H%m>Yf%!kc2 z<~`=O%vI*?=2y)J%(dn^bG`W;^SkEH&0m;Ln*VP8(tOH%+T3J5WB%6MZ2r#tv-ubE z|CoO=|I2*d9B2Ofj@%uN9WU-Ywd19oeNfNx9ZBZbcb?hNxZ|rG+jriz>w}%DT}iu= zcgf$5cpfY%sbB#Zxx{Yej3V3Oe8%qmFM%0t0()@1+?dOb3#<|M@B07vcjg;E&N!hq zw;&(WM9;>h@Nsy1bgaxOa%MZ0(=3_lELg_mZ6~w)7pY0z!DJ4Nv;DC6WB$b$P^D7j zhRfTl%=GC|WU3s-B0y=J%97v;6aoOpIf|1_AjSwC^u6FFdtu8G?mxwQwZbkH?1WwYcXhh|{i}U?ua}Ny9}Frw6CXiU zx^x|3O51{h!lHbZn`g5-ZFwcm{G1||2R1mPRYsmOe<@~g@Xc>pXv+ehn{(ALmxR4MEG?zX8F`A%v-oclCr2 z8=!-ZmHh^UG7h1a`sB~oh7iP_{0#_CatIOXii%%D(BoU^*)zWZ;TaAgNO1AFw+>qC%x=>dIBpKC*) zUV429axXokzqO_(gb4v0sFz+Jg4|2%^~dhKHU#RW*M}hY(qsBNc^~uBp&JM4rPqfb z_tFpbr=GYr4%ADp4?*swpX#%C%eWE;e=og01i6=frvLfauW=v<)Jv}qLGGnr>X&6* z69Vt0*M}hY(yy>SzcvKwrPqfb_tIwl6EF3IFp;+he=og01i6>~pzm|*wINV1y*>oF zm;R)G>D09$P%phc1i6>CUe%(yYk>ul%g^*;n1YKIV9CM2kaK3Qz*JpgD*|g86K^1e z)((ifu+p@d!2PB9ns{mC7b8~=Un(rfUz!KL062;{u44IMA#lWwWEmR3$SVOl94*R& zoPqz$l>?-WLywg}Rt}rI?7ndW01*x z#h6AMgX+MTb{vd{p5JbEU_7Cf$Mqq|W7;R7EWIa$IROYXrd=O`Jf?jf%G}q6Kx5kV zA;@Fe=}=aGZ3r}`T_1uxrZrzhhwfU?n09>#@|gC||40WK)2tQ=x`VR7XC5q`VizXt?ep01R(G+?fMYpG0k@s9l9aVn09>#@|dO#yRtpV5d34> z^&!Y(T4>mn?V%e2jcM11AdhLi!4T`&qPii_n09>#@|YHT6@#G z869~~CYMj+C-DLK_Gk&y1x->viBW_6QpI;G{-cV&T=9z(zd-R9DL(N^=zY85W8uW( z4=MgU#lK(i?@|0Yia$&7?@;_q#h;=07R8^c_)`==UGXO={zS#URq=08{4~WMtN3FS zKUMLQ6+cPwX)mq|x=npE_a`X+tpR^DPrpU&_eUx5M8zM${qbtqPg5uGcp7$w1UF4R zOz~--Nb#ZE9~bbAN}Tv&x}b6DSniJr_y!(NRr~!RJf5tU{S-AZ{B%JnYT^Uyf|3+J zSxtOwU64ufZ&v)#il3A_m(!z^c%q@UvNq3yQ!o z_GgxNTKTr(#YzhCX-QuDik%o(^jPz7F0HaRLrRj8awYVfk`nCsDND-fn51n`07oWTByH}eW}lWoiV8%4^hWVGkxBc9(QfG#1Y2GPONeE!`1565raFCa*kF~xl42Eh zj)X01tt4zB+eM7|)Dm>-$xhf|Z;U7XQf~paiD53iv%j;UdN{$OQ~A5A<05_b9%+& zoz1!RupMhJk!yI^`_BtuurmVdqpZ2`kavSYA1MphpjM5aHsm{H!4rKLFIl21HOjGBK7JW^HmZ0Jn72G zuKGbLp&xMR!y?U0pcoF7;SD%17qnNUneSteE?7J@=RS9gP-<0);!%!#$ZI@j)IU|K zZ;&OHvfOKk6;?M>7G4$INtN)IM;RN&&P~m+Eq?{?J+2?HjpffTZ%rS@c8q#d2)&Ux z5@#`%sB#mOy#!^Rb+1s`th=~;H!q=IvP$Dd9Y(8Gk$1D;?tw%Tt4uu0zTC!|6TfM_ zzl!BgUDRq#VbzIWvJj6@!E>Sn(Ck+B)6|@Y#VU60m~;N}ZOrk_Q@x=+kw=|Tmsm|XWp<``ATm_;~j6WM@QD5o7T^XEU=3OkDQ zZ9@lB{a7OEH}XdYBmT&8|F~CBUfF%=cK{{Kygcy%yv`G6ahk#CKfNAuQ1)~?#k*cLQe z)E#Y?>RtwvL}rjZH+kPOR!WJg=G7pUsJE69y7!@={P|_~HSbk1YV%uEZa13E7Wq>> zC6n$ckSCE1IK&DPRibsTT>2K3mT3J)f~oILEM+LYQtp4a!H(#;MYU?waDpk9r_xcY z`x84i?ZbKEHW}FSh&_QAJ2$_)_5N2-&9eLPLf)~Q`>cC02=I#WuDw_89rNV(@Qi@H zD#NVe9bJ5dIi`KkYS!`!_s?1YAK;z4P^(pcWs84+ZuNEC>4T~DV zs@bC~DiH{(S(H)T8(G4hRzDA~*Ny51cAduK6}WalShMggGb|U}&04v1 zH47WaKkimkVlFXpMr-Gs7c(1Xs)D(O~r}JO!$I7wB1F zG;|58I7%utKnp=gEHcIh32XT4oMuRL%+J(J){@62YdM}mkg(dS3yz$@@r;_LewV)A z4|1E|A$xz~UepijFX-cZrmlj=RO%D+(KJF-8Z=Cyw@Se05PD-mQC)ogFZ>0aMJ2qC z#J)77`)8T(Vj0*lRrF12CPd4z@#<{=Cd8@lBX5XM&QVei;W4&oKA_x)wmX~+Sc?v8 zWaHMVY1S4h<=0<_xvg;hcL&tRzClaAml@twvsigTm4zg-C5Ksw+<6~5EEtzO;#)` z+$#Ni#O(A@ZybR6VZN%>ltZx?e=M6~EFns61x_JyKFw8vnmkPN@~F5LQx;|fCDts= zYc<(1(!R%pd93=rP!^fRs$s1)GV2Opi&^#LXDBiF8$SOzzNui7=K~6Wy}}6Q{e)7P z<^XvW>Utf2eTIU|V#I<}emn_l$YCmV;8;g9`2~Fxt0o(sKw>UDdk=!>#;xb0u;)Dj z9bHKyLwii*4-{jwBUyF2nL%cXR?m}m0y@-&YZ{-~;W=XoZq7Sezj=sAHrdCn0^<=88Dh8kh+ zM+vK*V5iW)K;-Wx|EYEM|3%xI$46aV{p06;KC@*e%S>jHp@L*IY9K)fpcyM|g#<*! zN?0Tm?GR-PD4Sb+)Yj|?dss?PS`9mb%P3+{w4!KH(Hiy9So}5}s#I{nR7RuS_`c7% zpUFaP`#itppSiDl=Pu`-d+yopx%V@Rj-q+~EIr;mJ^w4&L`T~hgQ^2S03j^xZ&;;; z%~op;n!l{Uo)#`uhmF_r2pHqaBy8CJplfxX`5^Cy`!I(hgnN%~^Gl`BdoCl=7F>h>Mv(7p)u=b@CLZB&aH1}b(pV@c z_g!c{!2dzxEH%DtT1Qdv>)kP^M<-A|#|&(Tivm&c9j7qh?-45Q){saGjFdJea{CsLPPvc;%|8lzsJ82u$) zHV_P#Ra?5LeTDs;Hw;HBnA}@*qPQ*_z#ng2nq9&w)iN$*10cn%R+nbh#B(SX+CdEi z1qkyN`Omyv&;57iI@AO#p%+&UF?Rn~(BN&R zw;9V1ns}0;h41ioY8X{b`A;!+J>I?YU-U^c$m@R6Y~th#=qQf5Kt7eVzJp$nfMb3o z_zYZxr|`jjwg{TF}+V&K=6M?>t4fI>>(qWb7t#awNl8< zuyLW?u(fi+;)Q82R@g?Zd#SnD<6~sC*ZT~Qs*82~SB%cMfk$dKVn%4-JKA$%Mv6?# zNKHUp7CK0VpY=!wn}OgqF3dKxpNvc{w8yN%!62|-gTQ3N8fO`mEXqM&l9-LW;C>N` z#vo0D>0&7wd7}Cm*`j+JdGcQdSvkF^hR$6edN~?YfIh97ft{ka8o7pjP&OI4(!j{G z+UbEFhq91GMiG@2o+4ui%|~)$QBOhvKVxxigv|gaV`#xkQz~v8V^l%~;2h`$4S4S5 zo2jAH!3JYPWSIhq9M`-q^y13+jX$J$;9!Me4MdR;yKyTu(hQ|$QAKT&$bgwuDVt_% z$X4o_w}QJdpRk~ofqWShRrf*_GcN(18RIBaxXOl&u&y)+nz!1CK4DBX@B}m&*YI{S zjEUy?Jcp@Pj>;-0osRi+gUM*_@6nt&m{9^k+2DDx#86-!sc&063tI+-*VEj{gLLB^ z#)iUGWN0PBxWlTc=QqRXga1?CRh-={K?Ar= zH(*|1_VJdgf!I0B=hfZhokeBzDH%VfhG~A59mhw{X1j4gdyTX3=hDu37@{DZnfSU= zaLhi+H7$*TmEgOM%E@kZ5$7so(rQei&*+qFo&%JO<|gzRsiC;3lT4BC0Y4Ha1p-Js z6v)7Aom2>Oj+&rIsAnT}9f7`J#`P5MN72w&j3*;_;hzwwEg&Fl>M77)&+k6yFF^|Q zMbei7XgAr9|0r4v7Y&|6rX5uEplZ|-Pir&MXT~8gfjkO`0@4Ri&wpWg$k@!tG5~xm zQe&3ORHDAKWgv3|$n6jrdyQm>0%NbWkBnL{PGc`swAU*bKhP)oKrp}tN{P;b_S8gy zVf-Jp$bT7a)_*hc-&zU`r?U6`WE?bTT3<3+n5ja9$aw4v;(=N)m5me_VpO&sB6Fbt zZ{Dsv_z#ln2gR_iH>>4PK!Cw3R1xRIme~SIUPb2~P|IWF4r(2x@F0X#dSV1iI;pP{ z$ch#Rp%(~CFw^uj|EMPoR#|+Q$%bW4=1&c?7?^kyv(08bYiF?$zlij5{K>GvFf!f( zx4Ha41uwY2i%`a6anfXQKm|a#{!i6U%Y>q{c{TnmoX;- zcH>CEiCB?fowj(1H9Cg9s;0uP9K}3>v79k@OvIq^Csoy6S9j4+W;#eH)N0y{&oHs^ z! zr=B(7&)8#jST8ea-k8h-)tD64!8=-v8;JSBab*E=wk!YiFszwlRE|AJCLFt1 z4)c5pjXiW(bq<9NeLx2n>;0EwZo{Nev*OSn$XskRfCkMXi>(QnnimPtBB|#8poa+2 zLQ7{FR8`Z0R8px@Ik!oz1h)xSYFLU;6ZYRyJx~!qLh}*olHwe0=K?DM=QB9jq^hJH z8r(}>O?3d`lH!HBCU#?`ab=Tys(V!X)RBG|9-J@$l8KYM-OBscIxp`H@ZX~Ec zdtA)%dQa=+nDJxF^wQvt2OHf;MdPJV_CpO=y80cMj<*`b5H?#@V+V{gs;fmXm{W{; zCWa}RG)l~K8Lcx#e=%?5nzo|rIH98J^awYCyuY9jTgj%edJHsUP4lDYxRd*-<)x{? zMM8B(enMGi8l;}N;Q&Hdr8$rF0_GaAnN=`lX#tiadmgNL$Cu&NdXFu@jK=A-z*%m)mDQffZHMj`X8qbW}e`0!?mt!N>0J{Gm>q@vNrez$yf zCEbV(8$$!_v4#O>9u&w-?NJKe&N)Z+L1?Ob@SiB9<|BsfWnkih+A|xsiGo+ObF1e2Q**xG+0=FU3aBQRBR-I%edpwp=?0t(@Ux_WLxvX+~1(HH^VN z6Yhld`5}~127buU|H1+Qhy$u#yRMF=en8nzQEcTO$ZVmqXqbUui!V7vER^I_sfkmQ zvPutS|3?0!BDgcz=miS)cpGnqv~UbqJsR}M-X_7d@0hBUqYa}08`k_Sa%?He;gH!1 z$oOzbQ)I19_EAG|IW<15Ic*!*g)o78iWe{@*p$V8G$i4sYLNc>U=yN1a@}5KjFVz=F(#YGvbLiip=a6q9S%6Tj0)(x&8wleu3hhn+ z@$3x@yapFX8`vc0rRy9wclwLZn1gPIGb!xG(eS$G7m>Hds6DufY?;tJawxn+9YNwf zsl8OcwK}7U*g2Ko5XEL!r9`DqwqX-^QSVUbHdO3 zR5p`0(CTPesT%NUYzSIm0>g!D;Ady-q8+O6#7y>%Y^Ji*H_0}bqDYWy1V1a;ET=TK zd;u_wDmX>74YP8pF0!=Wq7P}_!L?-j0Ua-Dq}GoNmPfWr!LR$Wo)toF^!Fjr#fXU& zt%>JIUZmmeLIEh!v2`+t_ArHR5z%9NKx}3tCb$&n z1QMH@Q~T@*ZTsIax73Kybkze zK4?(^hJBMlw^}(fgneY&h6Zel;=eWu-7YRRo2D#akR8{y2m~|)%4Ss?S;~e{Ma<#N zuY?&tiEPmIshouk3CFEdw<&dqGYpPB@;?1VUS@5{PTPPkE zcEdD+C1_Gq8fRqrUu+A+O<`L|A;|a9cS>^J?P_1-+}6wrRS{X*T2QGc_H!6iQdrZo zP&c?o8WdDYgDF)#8=#OIOsP^0rSLWH)Y~wsx8dVB=-5KGO0bJ9)X4u~Q}TbC-vP+{879B^)U14F6~svo#QdRIv{e70324Z(kVa z!t$`0Sr0LvgO&iU@uYBQFDwoC$h>jQHQv$5f5RjVn%-Ipm8RC6_W|(P!!^esC7f{` zPa15C+I}PYE|Lo9yS878?JG1`S8>}}&^R%|N9faUfM+E^$+tnq75XW^1|sCr=KPp$ z_d0SDk<+MqT~uP*>u5fmyf9RXXNaLvJcqo0?Ad2WjX^x@dunMc73&TF6OMVdfwV)B zp*FOiPcJI7Ji%^IJAv%)VaFY!(BhsA;LAgEG|*_BE-I?+_Y^aBQ0O6LLbJj&_hFNS zH>vtao!3&LY@eEWOemikM5oAh44#E-n!t{0_kan7qVL)uQ?(@(o0?4pE-J%`0~bOs z@TJT7gD*qSY9FeR{0~g}Focvqor!%rZ8#My7Zcca3b`CA&~^YwgUKfNglr4XUE1!z z4xi?T=f`klAojyOoIA>Vo^e(igK+y$CkMsuu$y|)4p|4g3&;1v*<#oSWg(xJLsW-- zxdrG2?9fkk2MXcSNvt$FbM(uHX^H<9)mTI%Q?d8Arh+4p*WP+L6*Y}Miwns>>>%T4rKPzsc%nI<`#uVP73|Zq9sW>u;aw34Swb_!HKY8`EXt2=5&qZOEBAon%HmE z#9j_!*VqmB#4hxn7#xG)9hw)6lF@@Z{&}bN@NMg1^>~vlM;0gq{N)%DEI;-Nv(b;K zta%*S$6EXozGmdcY0^kg2rsJg)+AI8i{YZM9|{>0kR29Njl!wclbiC!(?IM~E*N*% zK#b4xfdXtNd&GF4_(8H?Cr&5(bqOXu6}nB}LUp9Lg;g9qo`pIY5C7R-U~3mDMNqdKTm-h5_QMeJu_zdh#Hs?)Fn;JeF2inn zmiD{3Gliy|6(4gD<6=H8{f^maQ9z z^N-aS`)Mt2PfM(W{j|DdGDfISjfJ_J@|TK^;t(^}-m*qUFtY$4J9;#-KGV%%FjAJF zAj0a8hUGI}F~ks9?O@SPr}Nq*)CKO8s2_ZHmipd?dY(}d3+T;iNu;iIeGUEt5C|S< zui0<`+}O;sw&3(*CI5$w9zVycm9|!JZy5YANkQzvZSdZ$@2?HitPb{&_oWVm4sjIe zTUzz|v(CM(HNY>qoz3>XE z%JauM_X=`B@?!t-u&*Kq59A4*dks0P7{Unozr&d3Sn__VbI|$x9O^@lqYB$%AKP;$N(5-}3$#Sh7Gn^1vcg6xM2ZlDE) zmw$cv4YJ^lNyv?*3vSR=BIdOqea9qKffIm0KFGA1>BTzQn15tge9&d=`3ivP@WH#6 zm7%88RwNMD1r>0IWhJC2`B}=aqr8Vd(s3L1${ePpha+{tVhKrAjr;WI5NA+^E|`mU zthmTFbj;Ck-bTlvQsvzRIy-!ZF6Gdwien)piI@Y-?$wDzSl@e?QF4jyY>}pN?Sp_$ zR3#Rz1+_*U?+5JE<3=q`108p(Ds5ghGhXgJqffSr9kpx*Cb+O`D09p{&ElPO)@dh@ z<8m1m2;rp)Yhp;9ri07;Vk0k-e$98=zAY9l$A%|rm;kaMN zHlrGDLL?l*?AWCLLrp{-JGNt>A?i=tfjV~SL41y|VRUvWZqO>ww%GlSPgvph0ldoR}t#DC-kaQ(Gatn!d|1O=x7B4VE1a7(ePJ zrui}mVaI-I9FvEA1UGga$G0vBJ(IG1KV)1Bxdu}#^i1}EA;QER&xz;RHyn=Ls)0qN zaO}dVeFM8)&8BTo`I{8Ippo?s3tGqam*CQ4r!VJhjyJ>;<#(Q4J}+n$UXXEtB)&fh6*%63Wael>CO5{!TbMLrBnS~G z&OGycCcfXXRi5zcJ3YeEok@DQ0Ebkt+!9rmpvvH`D$8`0MpVI(@(Ltb6kz+vq)Z#8iDR;_ z#Qt-{6+u^otg46@tDjr}kBhM;&?q&-+Ix@*eF=wVf#pIrc-gM(#j)i0dvE3;4FdU^ zz#x{mPrZ-SaScljaIKvIh1Kj4)V32~si)cB;ArX)Po*NlDlwbmd|(kRex3ps=wUe; zhMNQB4-&9j2b~?4JXr&DVvj+R1fXC+grJuPq!$Ya#Z-sbEqeu)DhU5493p2nMktah6EBl06Gw2Bv-GeV+Uspt zqkWOO)zRflD9l?cB@kMp=OUe4EcD_WsD4>$bkWO&!q1#}IEp@$5*TXXlbee(Rcd16 zbuqHQU^$XROevdz2+(1L&biCn!U)-AZk8OA6jLk5Lpygd3A2!z!2kWoVAan#0(^q~ zicl_ZqR{=SLbkR>d6B8O<|ypq@s6BP0#b0Nxs^LBGGE~T^v-c!t!e-#c84AT5%ZVv z^3Tsb84nrg`fdubHxzdq5JiIK83QdsffIcXIj^@i7kI&&G+?-)5K8X69&Q5>Zu3LG zjpwjTMf}ombapR=9u)1@ISrEQtON$lTSQKGc5!bZjq7_>!9akM_3NW4FAgkP1pb0k z(#68-oHJwuUq)i5#%6Pzs(|agl2?=4l|@GM*)a!1JHqKKv*w^_@FqE9cizNRY&&j2 z#9)xZwbUHR>}Y~{6&c~kxkXo5Y}8jgPtL_yP1f~|3YbaGDr^!c-CLjmE~DU94bq*o zU{q87oI6z?2yf_aXK}KX%3i4M}5rScGe2%seoZC+z)PrQKbJDZBz*7sTga=U821 z^f}us`ZV8S(r84Lakly$ zA;9l8w_y&*>CFXtd1heI0?^Cz2w;I56f4Fu4$A>5uXM+A_VyI)IeRU^-ffkSv**B- z1h$>?^qCW5($M#-g3AqJVt7gL5?rCz*2=+O2RIF{%-!(zWFAm51U;`Yv*P{06N7x$ zlBDt~RJR@~iJjBY7Ke-~3Kmo4 zs|h;}fl@fIM+{w!a(*B=U%hngYf#%_=jQvMc(Sgc6)ays%m_4K4>Gg_7H2*i5?JhZ zb04~P{@xmv+u2&yNW!9yHSynq3$t;6gslQ3+8n?L-j5_C-1%3D(?QpB+m|-hpQPgx z)8oY-!96vWoPQNq*x5KaM?7YeVUrw{@mx0k57ASc^l60o!F|H+;N%m%9Dg;p0zmh0 z^C3z2Kh?(m35b`!Bl3MZxgh^w|H1QI78;8uJrWi}bTVwU?tvn8jb3&n1NftQgg;^` z+2T~22*}`6o0umd;Sog2Wb5%b4r07*KuBW(C)ttlnLE=tvG2^_Ue0QS=~aruHrzi# z;ee2y*jZfIMnvl#XeW8r7!{Xuaz+#zhs3pEr2%|H zNYI-9k?t&;d%*$-g}AbL2lQ+F$TEyrud{^(_{@jT7RYw5v2Nr@bLdjGQ8UPOvGn4* zk`v{rz{cx&!e3Krc)U|ZS9A^K5iVFfTv(;+BIZ4;lxl6%>QkhlD=dYi zio#$7o$;{hLc=@|Cf8U!x*uCDi$e9h4f*_C&&c{uf*f2w#)g&X2EK~p8V@nZIhKZL z-aC!Tk$!+H_hnp@6B3q@>_)5#Q_h>QV_>Tqv3AnXo|bC z2b2J$Yzj4~jFBTK*hKRy5a@j)cK&n`=EA|Cy}G%UXal~1Q+0D~;j{aC7H>h*i1PZ#&H%xFN;zRX;H56vGroL;Y# zKCgI8k^v9nICclU0x^j7+X-`L^z6m~I3&OEAjUH)FoJ8FS}y~!1=bk8-!Qpw7qoul?xo~pEcj!Te78{r z+D*P&O&$3d1@8xGT*kMG=C{v_54u|dSX_rt2<^TI$!Y#?L4^Oqx@QmIGjEB)SFjtQ zd`U0fTq+y6n{YLGe`E?Z+6*&NLaz5EoW%tz`NsY~uulBo365f#zE9PL(*AG(OH_;N zeO>s4ipGA6;1*$Pt`DsF@rv1AdEeZ{YpWwyKHLMyvb?P`k(ks1VFRi5@mhFl>Y#B- z?rRd?Q@N$gzHZQga&mpH2I4X-xXt{?GTSSkLeMU=y+_=cy@SIRS03=rP{~sew6zEH zQm@KB2V~30xfbZDSFd!S%38{wsZky?qfD(|!)oR2OJ)80o<0r$xwBcQxvryi7J_;~ z8l9-Zt4X1eLtHz*6{t;~15}m2A*?73f{&+ZxGz)#C*sh0txDo#7l0UVKBQ2X&4mv| z##4AL7^mF2iH)jP9hfagMQox0Ak4Wgg%b|B4S`UCMF1kSmR>neIdB^ulWvCK141w{ z+m)FLhCA2Xhxvt}L9nLUY`Bk@l;lserhy@b<+O&yIdG8RGwEET29r)2 zWZ2$Da=!UEkC%sbP_y-ZPrAU|BZUS*e@Pm|Tl@5hK~TOTxNT*qX=AxC+J8I+@5AV_ zfu!a%b11i)23hbtB~4QmF@-Bpx|fR?$u>NB7|m@H(r90DZPFEnv3m$5U29b5Aqfkg zNa90eU}=lGgn0q(3UQSmq4{(g_#^7ybt*@MONGnQN{+bMXv;egb}u(7;Dl>27^K4~fv3_BHg zk*i`H7bIBH4lrK7ZDt;0@TVHP+YBc!)ls8j>=sIDN3sWrkXyrfbUd_*8njr#0T*y) zzI7C_6_Y4Q;$Lj5kwd^t(maZdt)~e`!9UTN&aFNw8{xGJ83pzw^EG5gvAMEOpSWEU z5u9;Y@O&)z5iI!aywPoK+ceeP34RUIxKpFYM`&0)1w_Q&RW?5u?cLP1KEwC_+Q{nscKwDJi``kbSu~j8=jv-qUANU~mX$0@n zo$XX9J^nk&|Jl0#^UAPjw~=1msVcz>&Z4O^3+`nu`&&2CL+ucJd@lN3d*u^U0lWBJLPV}X;p}lVmytD{-#Y zLP_7^KPM%9!{e!Pt-gk}PLw3_PnBrjC~gi3?>XHiouE!$?MCx@+tvCeWXiX_-XTaR ztftBP=(M)#aQO~7-!V~?+_vv%kUEDJjLbJ+cCt^-jaxThdG51>t+~^nS>;hk2mibM z!VBCm>Wv}_X9_Sntj-}9Qs}Q;CD70QW+s*E<@wUM}NgkEN{&1T7mnZ+(5j~p_rjdH* zV0f2d(LSutK0W%-)3Y9ZrctQcT7HWdw0u9xVgj0+rkjwIF7(9aQ&mWTvP(aqEA~kfFfIv>%W8M zJVbN*?@&t_KbxC-4)kGHH>4l}AlXLuZhwL^D< z>cDBWuMR#dH+)vQ-7Y<8L}6efT(t{M8JNxw>g3ll!T^_5)2N4*;BFEA;?~m1`Jv?j zIiuYJk!p&5svLTnRvaL1cfo}rUWfb&I9Dz`)w!8&di&B-pZpR+1Z5HKfd6InYZmaow!jri&V(}# zrq=+NUNSKWxOcZ0PM*r6))MOmxPbr$?|#xa3*IgF6Uqd&!lK2N@wV0}Lvo0O&5h?T zMLXu~8g(t;tz+S>fQ|{tWi9G4jq(#B?cHx`>^=wLn?#{?Mjb}?^bw63Hf0SIEcc7% z!@NdsXjtACJ;eP!NMpRs{f2U&3c9XX`DWLN9}d*o>kfXMrRv-3&RcyRmE})5{mC2H z+PFTEf!M8ja=*d;o~q>;+>7DS!POp{C_L_WMd^0Gt08;$%&ubwy4L?40o0dKXqATS z_vj3S@_R7HAv_0T6p+P*<87WkGSIR?hc7=cYkR) zxsbc*^lQk06XzZg4cGk@rZR&<8>~L%P|1B-A4PA$2&?S5r{&;c0y~fxr5uYw^p;7$;FyBuEt*5WK7gXoz2MkVvdjni}IFIgn zuv64D?8cj5F^n8)Yl1onZt6Kt)Dd>PpbF*kf(NoJHUC8eVuoC4wRLwQ3B3#o@JZyn74?zXj zg-}tWA%S`&s_gi?naj=bstc0TaT={Z)U*8|>r0S-vivUXW%MNiF0jO+??y-FkP|m< zAGwkmC?i|3X&rHEK1slghG&ljl0Ms??!!zLs3x zRElQFiZSqNAT^Ji`7OBOzDUDApak<_jprxSJn9nUKy~%Hxq;>h;APTt#K+R6FMxTk zv@oG|ijpV`kV&+2q@RlQ=5h`L?bcJs8etA{9tu?ncS}Bru2})GgrWeEd{XaJ78>In zyBDIt2ny+=HxG^-jWC6D2p$~lW$oAe`S2RqRi4}ay-J^pio>+&VR0LHmdQmmPmN)Yd5k=D3a5`3F1|_QtPX_>t-`#;*GV{p zXBqSm+1l2jE~73ZS2tK=*b#l>;m2LNlrKz$t9b5{N$0J>G{;kDt<^x-y=R^HUp!4l z^(b&f9ju2O^E&tNp1ckZb=BiU#q%pFdmEdC13#hpTN+?h;_@OtALH31hfyit!fiK+ zQoijO%b2%a;pHLT2qK-pE}#>QTd!f+DWb=-UNh=l=5Ta|UizGUiaZ>E)Yst^y{B)> zR+*T(4cm7WOj68mZQtFm8O|4)$kU=<(Bap0oGgT&o#ux0MGhL-7UWXn^_JbOcU!r)GQ75=l|OA-%HYU zvICFvu=*+w_rT!S5BDf}3<#P4xKz1*sqpY4`emVQaEh*{s~r?Q`wO54oz=K8_a7jv z!Se@rr7yDzZOg@I%Jj|@grIBI$nrh_@TM@p_N51sZO}FNp&%seUc}a}$72XMBSOvp zmIj^}u!IJ9ZivlscB9qBueKyt%%}y!#lm%?+}?$9qXJZr%s}8|ayvXH_fiW-0TUauZ`|o#%DvFF3>W&JyO&*ah>4GE_Edo#)e2jI7piU!dmF)&4PfPKLu~xVhXd$+GprZBqU&4bYB#UC9Bo8&09+ay2d44_?5x$#j*!;JbOW3uV(0*ZoNoN@dJDo)5{kLv@%CJow%e$Z5*d0t7u#*4B zZfvyc;l@6^2K4gJZft|z!-JaOituKm0c<=DFUdq9))pp|Jfff;;8&{ni3;0`03wec z!QhKrs3P)#{aJZ^!dwW=Dp80A%gFXSnF{8|kuvn6oTMe=d`z9D(7ik(P>)ne{t28G z9C;*#6F!3Ku-3ZKXs}Bm;jKthLvbPvhoanepoV^i!aY_4_%1AIL7~$ANy*n> zyuVUN+cL>Fa)Z>iO*#UFR|U^PU{_)16jT^|`ky>m0$-AUVys3KRPt1d&uciR_5>c! zgz;$-`qbPT!%Bb-Ps}<#46YQJlU#a+%z?_t_H-*ZpJDP1?c|xLB8BgAp}0Y<8*zO4 z&&N;6^HgmiV)A=gridlxqYY4&UJjThPF1p%-EZ+GtLBCBo>lT_PuKci~L}(b6sSdjKQ>aEGgpFmKDHe)-n_P+i$|>|K z87T8j?I9R${)T5%W9D*#sJZ-XoIWDS!RaHCJaXX_Dt`!0ACW+bdQf)_q2KLwfQ7>6 zx535J^?Ns_mrnTTLiL^ zAxS*i#m2|}H&m1Fd}!%+lP`zCMFfgYrmG4t0o+A&LRvtQAXHF{J3GiLOqP#yQF;7+MS&8|mJ zrDjlDrkJKaf0uB;8@DQ#klbL~mdR!05%jWQ*pJGmw*Y;OAJ?Zc0f;p;(`YE8$zN z(Lxizi`jW$npq5RQ__3Acd?;217zl5>$rl=V|MU4U{j`iPlCsh@a>Y6AOjC3XVk#F zO6iB32Z8f!a|xWNg2yvNc06Z1TUbvi=Szd|R!*`yw*7)sg9YD4^0%_25GpK!dod6 zSreZ>Ne_hMC!CY~`1@eZxSaESaY&_npF%HWXQm96Ma5H!^V`>kQpU>;NGU?DiB=Rb z@RX^;FEVxbMWznF$n@y{l68`zlT@4#AEcCPj2}#U5Q!e|8nc$s^PG?k5{)I1u*mV_ zd*F2}wY{YfVD26PoLK4iGNV{`IP^C$DM|!8K*}%D6B~>mhiWQ)PIAfnthW#o%#lTw z<7$S?<}FNwsQsIp))pqDGxD=8Wnb1LZl)Agbm1XCgv~XFLfV&?a;Up-I^huk-iE2S zf_4qWkTWeYdtwZ_@tRgoPn1yuB{5~8HdHF1U`Ye6>2aIq0P2(q2}n<=z<3KOw9$f$ zy9RwSwW|EYb$uSefSZDElBe8@x&Ql{s-RJ0Dp9(X*$kA7D3YU* zyW-&o@TzAy1%HJE|NRmkbe!ks({%iC(~1eBT3PcdYT9h2)ksL;C{21#2esV{0P&LLHrgiJh4Eqf>30 z=)~KFr&=~6x%^ZUUVwl5s#E1#sR7SPlx%~d6p2S?(uqjjt2-*`MElZL4^<&q`Rd2j zbi94dYt9s!mWa|6n(#v46;NwaE3Ql>Nx{kH1%sUAz&xl)4C~ zY~nIu{ZnWuxRvIjFa>5H>ryD>WUD#|`>zD^`$<8(;Ky|0cbCSeT!Z9C@jJ%T@!u83 z*B6T)Gv$~(vWmqKf<7jG)0AWAx-VFXjL_0$-@-JZM{o)S!#3p|ZPD)6rmVJXQr^|p z?tUb4;?RrAG0iV1bAaV`g}-(D>Cb;Jj@FdlQ$zlET6_UD=8sp84-jAM=SPJ!EMIKO zQOg%=xoe@Do+7}Bt489(g(9)~JTct63?uDhSuficg={pXd?xer=)x3uzP`&N$Qy4p z#965ccONzadjzdsa2m+AuXsaKzD8~wZxR+~E57YLIts@dDSs2oEv4(cLtAcgc|R2o zYPL_JR0IC`>O?P(8W`4NOenOR4>BxV9}H5Ldqd`snxyWFIYK^?Dyb>zdn1QPFW3mM zi0*5zk1ud>pJL;TqBo1`dOi8W4`+(TofYIA~;WAE1YIS|kX8 z{nV&L;`|USXg7s+NzSuK980PF#j%vy{|v{HiyI{DRGEVpzBNq6d%1$PmXwdnMK9oK z$^j_6EUQD48|>-h+Fvjibe4KP{sS$olXgLzexP~qVVyjp6U|hEaEmbM@0G%k)*P`o z%!P4t?~;*ohz6*BoD7sI#ZV`?vmH9wsgs9v(lr7+o*ZoHc;Q1z9RcyOgHnH_QGS`^ zR$hh%exsC-WIIb0)XBekN_iQfHJdtt8CY6m5809QwdLP{Bxn?u%73nNu`R$SY7<)`3CpS=yE}T|7I2=i9a;6;(Qi~Hg7Oklh(Pupq1N+$r zPqF^Pv43FU$)BJXv3j)1Xr2S~q(&$fx+*>(9iCtiv_8L0osCEI4pHh1yzcQJ3c=)X zfoPffWn^$dB&W_+e3QKUzX#+$OB)r#Z{^M6TXUTw$a?e^3{+18&atWp3I?2`o`riD z;BLU3Nlr%QvBEPCzOKQyNR@^}1EUJDwyB4q9<0K{d}6A*tZ?zo;H^uuOE#fFmUEG& zC1I6WW-BX7S-#>KV5%mivNIqnEqWsqrKR!W8>w+J9x&TZH{n|Bf(_brwFP`PHU2I* zJCZxV^`{M?f@L)K$Ph}cN6yK)n~$W%2Uj773*}p>5nY$VaR$xmQGJ!FfN26T-9<=D z%2|TT${ts$zA2ca&#qH9aAAOxK{>9}b)2)MZV-JJPf0bos3hGrpP@X|J(=Y&p-cHY;v+N$7;cgNGD5F0MT=$O;-la!p|0jGNhHiI2=Xk62 z#5Htb)i?_XkpMt;JvKrm2HC*)Mtmf#yvNvZ_9;qzRhk1m{E(w}29inqOuOD4LJZz4 zB-k<`BpBfw*cQm0ZB!uGG8MN0vEzu?l!fN64RClQKKuv2n9R=;!yYSp@e~qm@FRC1 zD22P>+0(WfzBItn@MOE;d}%GEBGLk9kulUna`KNzN+|U>-SpC|sz*=Aq!FbqRL(P6 z>%d+qdmn`PC!_Lx5BJFi0A@QMN4(d3WYnWi2I7HnNaXqiV5x*NJoOv+*};BKBGPFR zr6ma_d=qps5#}7oZIa|B6ssk2V2|9#eXT%71Wm@)G;BLF_}+ZGK;R9q#D-Ebi=) zNNvUI4uIt5;2qR-dB>V-unuVvyd?cRrKO4}`1ll<@#(DNse-e#QqjcWCKS{$g8&oI zCRCWY1~w2J!q~-WVk5w=GE6LZ8djQ<2)-8NJ^&N{_)Fl|TfuEk#+$YpHT)km7HqDx zJUtL{?e#Py3qlcSjUd7lRfdClxE*RbX$X#+!BK{sC&PxJ4|4MXbaVTf*2e~*W{^i< zknkTr);J^&Rr*qzzKNVR82TWtp6}=XIu}M{TL3_A{>9~J4lKdq<95TWUNmHv8wSI2 zwZTuCpn(MvbGPt*=#gJg+V_RKg`wA}g%qs7RDh7n)FoC9H$Bq|p|=9E{kl&pSApPh zqcseU89ABKvLEUsI=fsL5@0!wTz3O@+ofFzj=LNiI5%v8B9C4^`T*e&YgNwKaAXN5D*I(Q zrTv5!tX&Xa7%{g;m|if@Msn8D3IBrloKtihRa^;rL0Bg5Q~}TnqZhseUpCDRji9ud ztiL1zSkh)A$3e?dlegNa97?-g_Iny`1JVw94AD$T-b7NdL!~XyP{SX>&r(akHjTg8 z;BS7VEfPw`H@}#mlV6g}6}U?hJQ>JajXwjyNhj8py<4Klr`;nfZMn4?;npghWb?9H z3+mQ%jpPdCz`?GULa9>JT}29$GbE`9;hnGN$(x4r)Hlh87+p--H<1=({Wfx{XS0fg0U7aNW=cq ztOP&|`5w48vy05t!V)sUp+|ctb1jlI%EY!upMS;(oLD?7!7kLprS}?*`uikl4?s)! zfXv5{{DI6TG@Sp!-aI;b=09%sQS7C;>h*NSgfSH1#$$@uc~k~OrtK2+coUyX)7<7! zGaXBnhIsauODOHBF5nTc?E}l3HV%9c$$0V^Nbm}?RttM8o-~`GPV-t&?-QsQ^MD$d zFB>zK(w-OW)`LueU014T3Bu2?#65X(FGPZ9i$RJ-l=c!Vw+|`pWkCV-EPT`>d&nWx zL&Hte($I3d0wnm|U`Aj@GpOe`WV*52N+(9We@7VR_zVB%j*^Yw&&!$Et`;0?hd4 zN8^iO#y9UKUqAS-cg3?2N4?_Fc+pLmLl&<}!{}^o*El+x+P0$5!=p2WfQP_-&j#~2 z&T66llto$x9UbkCFNTPGDK);@1iQciR|7a-Hl-cIV`@44y&hJ<(~hyU&~rCwWQb1W zUoM?Ruj0=5Q*mjhftT?t|M;_K3ps~%7^#z=!r$ZYz@OX-4z~Crb+moy1*HZxj) zJ~;;rI?4MZQ0p=r>N0v%n^k25=WyXu!_o?IRs%PT9s!?$fDgi3WEhwjk_t)mW1{$2 z+vIePveeq4Ttf7Ym0o;0dJ1kk{bpmL3Ngd|36<^sf|FQe3x#(=Q*E}l{)D1~g|3A; z4umTn5|3$c%jpg zZ#%v}&4jU~_Dz$hKsF;>z{?aT;a+5Piicd6AW0+F_mTL?bt%QBq{puq0Y-+J7pY4k z%Wx|b^5Khw#sbLr<$v!i47;WkvOgAa#9?}MuwdUJNjVpaUXChp&OuWxo`tTB_%GnC z*S5?8?6K$^?&Uz+=EUcPVxc4PD*#~V16FbPzs?^2wa2dr)BB-6PE63=OCv)Ru7dHa`Ucs+zZ-)>SoBQl;9IW zXzu-m&>+aPEBODr`s{Akf_Cqr-Gf#;aZgz}(C)wKMH2)3S?`^H&XF4bR73dd`ET7KmM;1ir!EdpAggU zRsInP@W~1A$qDeu3BqwX3F@S;PVj^g3IP%*gkg!kETfliRcqSU8lXW9HG@k4m%qp* zz5Fjnh^fo*jR5Io=>Owh@EjckW&$Lme&j*&{vQ^*9o~E#;33zJ{eB3{(Sll6fp3(# z%}|^baLulDpdG47U(fP>t6AkIIsw1d`yFbiTL0e(6u`)a7fy83#xHcuzb0x5r~ND2 z=v>9ZSwk$9b9`48(l<(Z-E2J{KOo}B1~$7`A_4M5QUKU}U&jLu>Z_kox& z!V+1F!=gLiT-?Fn|I6R;>aMSYhT{C!`10TYh|@|mLO*ZnmtS^VW%vkkhZkhI4qgwZuSEf_Lo0a#qr1q7n-eItw- zT#EONL6x**u=LodUo7&@G6+%szRQqn!j~}kzZ9(P0>n!VEuy2-jDZCe6g%Ri%u1Pb z*YUm8H8g4%sFet4hIYs+=CsK^vJN&Oo$wq_JLX<08(oahnnBRS^@Fw|+h<6K@*iGc0iodVD`Ffdslax^!KNu9 z8NEc&OQs#2xeu&&SmOz|!GFgijt&@_^Kc;Q!`E=9X2zeg)7Vz=4S>OZ22`K;E1KLh6}Iv0zuTF+cDu$VP0nE&$=QmuVi?^P7u_ z`S`WBRitKht-F0Af8m9j`^I4Ojihcwf{zg1fWkBi)*^9Iuo?*zo*KQV%k}!L=$;Ecx<&s#%+|lmkkHr z+L|lE3HUtuel6TazKp$xe0T;F>zDerAQ>Jre%Q_TYoi8H_&!7wz#KqQg`2FL;8v~g zSv=kbVn-F816RR#Ps$vy@htWWzKb9@IGxb$6>&ZwQQZ6$rM(pvgGY{8Q12YR%bm?{ zFXGdzxI8S7c|V5UdWd{@1{4p;`C7pXF#1QDG~PmPA#!@4cjOrg-$$UOakj@LaahUF zk022^JWtpBodllwj_?Tw$Lwjy41Uy(p9}83rR+Us)HCq7vjw~$=iH4`CRxT6majwGc;QZ|8d)(=LD(W;e$gg6=0g!@JrnVNYO}g;@f})P zjFgWy`@Z2P=SoW8G@Q|SHue~Qe{%vC&W>O8jC`1R@n4XeL%Dl2ET?JyOLNo&4gLuD?B#PDaI;g_M4seEuWdfQ~7j|ESli$@dNYuc{j45JONSi(~L7ztg`bU8e{6 zgVnSKcM9w3|NoJ8p!h!~cmJ;pu~b>)M&a5GP>W2+vy|pNPBo@< z4jJx0i@<^&cW1{z~HK(y(Iw8#Ul!BO(yWz^pRzx7qCiUuOlTw`Jqh^W(b z%N0yS*S-c`z?ito!UTYSkaA%$$U zA9E;cBK$UEfX_DQOS7hR!j~R7IXL%mO<=cn*R0Q)xEM9-d)FM4`#6S`D4H6Khy75i zw*{!2BY{|(!DEfQ`_u1MYRqFmkM8;&C`hp`cU&0SAhqeHlm z`=_p_J@IQWap??nZG3r1rR>JUHmOujp#Ja982UU4=rtwh^TCc91tuOrtdhCh!4Y%adJ< z`%b)zzc7r4b10o(UFVv(GXP@8^UJ))j(|Z7L5}JAhH`KQ2);FlFCR3V;fzI=+|UA9 z1z+XFlLkTBqg`!}@$ki4AsZPe{Y%UbJM}Gvt<5aY$-EV}&}3NVU^MJoPSls*8nw(( zzTupijzX}YwI+)Yw9~yj&4s2PPV~HNLK4M~8$o_~_mW$S7r&8c*AHasKA_vZ0#Uc0 z{1BKJ-R}?v@Au-rHl7if__clU-%l?bi;!i;T3Ca4K_SoLpZ#d3I36fpGIP>+ zXxsJ~hx>y=<0|+kTv+O#2sn8)6TF-;4?_j8xYkaAcv%_GeH8m$q;_v{7R}wwsEg+A zkp@h(b3~N;=YXVuR@p#PZ=Hc{AtUg+F@Ei+b3d!`0tYm>4H}f?eauM|3HO=zsq~4h z?Oy~~phzrY0HHF1CL}J8RmMq+ct#AobiGLL;zZZj+C#{HyJ){iY-2zZw@aw5|8^+P z+|H;3FYvE0>IMZ_PS-swNkzr;oU4L<#tHT&s#NlSD~t-ARC0qAMwL$3{NNn_SBE!& zq!&O#59g&2s5dU&03y*P9$vbs9t72k8!4Z;S(ePaT z5Gx@5eY&$f-__Yuy*g__u1ibzAGC&LV)z$x|2N%X>scaf-qFb`Iys;dd}X0jO`rGI-avrL z74O>~26147Q4N+Jz*iYXys*IZEV@n-oQMeq#b<2z=3|S()v^F)5*F^S8p&ct7`~tC z|04MBCj6({eW5Xb;=3^aSuf0gZebq5P^lMAn5Vn`>wjK=&VNIEe>r3B=sIr#wCzy{ za2$^X*iQikhQzWFI2#fKv*M$^c~5E#J}N8be+^q^?({a%HRvJ_I7%Bd0bK?66v0sf zCfQ#=OSILESDAYBxdYX@cvwMu=cQO9*4?au)Czr6D_FX$C%ptlat=#u zRD!Vtrs(EZ2@PH}rke)4tnz@qR$^J@0e(BWi?Iae0a;x03}j(9Ccgd|nE0=WFMw!+ zf8uWys#F_-$w|nF^G2uZjUm} z*K54M@Jn$0F1JXaw%2%d)_58(+y66Nul^sncasGJdTjY0B*m=3RBjd7AIxkG(MJym;aH2 zauPT#!H=j?wtGAmvICQI%<`TTF4YERm3x0@_-Vrq#U=2xQ88!)1@`GGPt&}}vB~kL zq2#wv#y}jWpQemq@P{2j4%`h|Gc>aH+H3J2YjPODhW`S`MU)4Qivk&V15X=bQ4iwq z1jD{01|0s2=83Ol!R~qSi{8*wfCliX1`g}d-=KNz82vaW(c*a29GDgW7;h!A`IhTYl-{>!q zvJBu4l9uIuL4p6nN-%#*3suafDxuwsBneNzL)1OLHhNNb_FMRxzo1+^!GWN(^6eTH zD4tNBlhe4+{LHH<>syii0gg_|?s>N}@+QBAUBT<{mBz$ZK=KD%DBI#oaZ(1p(!HD# zCnajmjQ}Bd1}1WBO6x}qE-r&w;99U)!@|ZJ%O8H{Q#J%~$YElZ(%-@1xif+B87+T< zvYjIl^n%+&WM$Z_b(bXuA}h28U-9B9%E&boRLu;znFwuLkM|Ikf1KlDuTcxC%Lrl} z!a^^*PR1_|3Y=k_ljMz%LVS1N;&h`j?;XmJXc$$l18s0lB8P%w)Z6Xu=6o37-A{67 zAPf|gmEo1nN^}E0mBsuN4l^d>I5vj3Lk}%FYRw2}J;jvF3NlET4S=StFk4nn{%W8^ zD2BJf;**?UsZyqrQIM#~L5!%<>pwXG$hZ)8I4fp}24#73uvfr5W?h&24y=irC7U$z27j2mXm{$|yn(?U3W80(x?nu|*`B&K}`59#iNn<7#2Q7ms7kcgB~oGk((3 zD##eG{*zUZG38$~IR>z&Y)k;pzVwV)8kQLrOBaTlfs60mdU?hT7W6PAZEq@o$=3Pe_IDtbF6#BgO+FGn1jAew?<~cbc`FNf?zU##V3CECI`XV*v zd1%)QXy*h2v^o=WHDi?=4rQzo)ZzLrj8_c{yK6=Hvc5-)mj^T{%2KhBtvQ1YTquPgAyc|vaB%b{Y6wfcn+@Bb|b`VD2Z8SVQf-?5$Re2US^JkX-;#u%d6g~-u z4gV*?CWAMSKQp*T@7v|bdCqRz4ka<=hQm6tI0IdSYxp1In*B=fUo5HnKk!I}oNmsJ zmy)!m?G#J>GJY_D5bF&a{AW_}QgA*eW#IB@dp%vuK{zHwb>YQ_01_@*=)%UOu(>!# zu~K)u)oS;q(qEyIUM`kgvv;XVLQUXvRb;78Mp#A}Z{j8QRL)s?fmA{4)-*@FX&Vl- z*CT<5#0YJA*fyZ`3s(udmHE=6$^?L50vyv_&R0t7jW+m0+L>zz)c8D9Y6Q*OB?py* z`-DG>n}^Y0RLkkk?YP@n&v8gxSdM_v_PUgou3qkfSEU@@J0vCWv|%9hS+Ho)ZPK{phZ>*d&=u9*aS_*DMyQktUUF|qV zux(REX%LsVNZC`1o_4>VPJ>Rs0LNa}c z_ap1D5t4r{G=c9MUXNU+LGO>;r~oG-3XJdu+KHFM$~WNsvq{Xap~7*LNdw*o!#({4 z%_~o3`rr$IBeO3xqDsjYoXtDpcPJSMg=Oe$ zeGUf?pr)*QCh7mO_4*|c$tnOoX@}3n93}*5T3@!~uecNp0S)pOi)jHqa2N6;G|?lx zfUQ=HCtuH!{|YX`f8Y}ggdfo&dORDFzFBQgDWmleuRA}7oIi_V7^qc)6x7CfFrg(V z>$}yBxE|TW=&4sNdoj(oJEmNRe9FW-gAycTme`3qol)lEfbglXnc!BVKGZ^!SLfc^e91gE3{FYZj78p|@RNuV0{5;oHXxTdQWn*E>>W97PJU_UXg8{WiOgBx`m98$ zeYwNp1vU5vm!C3g@%=whrK80=L_SQze+xiv^0mqad=E1d79W-a?eurHSVZzShcwr~ za@;C?;$zR~)6t43A&8e^5ihN!jsr~y9YR=9+g|17HDdC9FCN|t6r^#OWF`;^t*h*P zz*3#~787&6%>SYWH9}=p=(*#;P!!&A4>hY1vF<|bm83;CQp02uHF49$%$J8$5&NS< zl`<`wsMftS0G5>pu$l{ASb3nJ0c5)JK>iE_{Q%`mDEu@tNO22C`;<-fn_t88j4D%b zx^u)Ge`<>c7oL;$x{iV^YAORS8#bklmGw6A-iU(-qdD__OtY>v3=Ik2-z-OSe(-e* zgd4Wg7VI&3CyIk7 zG6#h60C?{VJwMI~lFN>SDHCQOZ~GM>%(}Op+L_2%?4IQc7Pb4aqohWx3L&tUcSnio z<%Cx*Gg3o#w zrTc3o{Ls@9`N~Nb*JpOmaxCa92L}T$$7_UE+%_9&7*7f%8rux_vL?Jo69Zw=_)lsg zC={O3j&LP3e@=AaQLGVAfWy7fb37%Rpq0#y7l?1v*WC`vdUpev3icR}jy`++Cn|WN z7dca8$eK%k9xv${4+A-ytbyX(nXja)Ggx)q16h!96?acqj2>0k*%7unJKY-=Zs+Rm zdTHsuXcu;>rKPF8`*c`y2+Nx!$t?*0jf!?~o3AXWS=H>G7#C7_i>T+pOtF1~=L!`B zgJSyz&y^}rRdn18=e}DZ51#u!QOLiOGM=r2s#O^7QD{0! zSQCdwf)zSHuAFF)*nXD)Tnj*ma^7(|hiT4+P!!q?UkRvJVI4FO#oU=0 zfp$(-XCW6RfavV%%#t!Xk*hJm=>khjqB%HNkMLjl52Fh#U4gBFWgeA7ZQi8Y1f8j;S%j}7d==t?#O?9`a{H{WU5pe0z-gFzlHSIhe zm?|!Bl;s_!;9an}P6;2x=`rBE3D2E`?}8@aV1qwV6OW|^mum99SCjWrJy3-v@1+v7 z9E4SXn&E~s9#Y+@A5x7*8oq5w;956diq~f@`L>M-tmfP3HP(1~pq0G_T4fECcvwnv zOr8;5GXQh+^BgRc!za$KF7SP|pxlN?wrqsPJEQ^b5X&0zA-S2{v_L3SV6C@;%@BqfEd-N83|cWwH6bVa6RS&04mx&VBU0{&XiU;U|xS6P-)u( z=6kLK{##21X{ausLHLZZhGw<)Q@r&RxU_Cm=4yj6!X`k;0579{2)JJO2)tP(|b3gU;#f& zF9CiG|DGSv>t*}|L)Zh_-x9~DAp95p{q|vriwTr#rJV|XXn>y}Tq`I9yvpD2p)(qe zau&u%P_7`I(RlpTdK7$upIb$_s30Gs!=S!KhrxP+VNm{HyZ-Wu9{uzgA29}N7Yn~n zFTr*Uw$s>Ab{2#O`S^GCH2#V`DfKA!6eIkf*XwUM*hhd5fB(3e2E3Q)dvth90PgQ! z%#Qr>2g@_Aj!dv_X5shg0p%@>?&$haj{;|g%U-X9Qyza2?zFdu1* zV9IU5CHa%{C!1SyvsbOSW7!R>+uB!T-I3?aS6IS(SbJk|iCj%i8Z+lHIyuN%pdi#o4RxZfn0Qd-bZNt*h5$FTJyM z)tc-@YZg1~YZt9*Z?oT>y?n*uWp}hMU!0BL7DU83OIEFJU$MMUoR*V6C1-j;&J?p~ zS~azxU|Q}Jv3OpFSX^IRC@!8pxpn$tbE{a=x@JkCSiNGom}kx{$TsI^Pd1C@{KDKR zg;S=BbtR4B?8PhEmN2q~Vy-!Va!y{Zd73EAEiVzxx!HLIlb0@TTQr?~LrUiOL9J5? zmQJ3!bjkN9@Bat=KcWF^RjqXfYHIqkWeYQRE>J6j{c|iKpIDYDqa*|88DR7XGksq^ z#nQ!9)nZ9eV-X?v$S#?llWWeIJe_4+d2(~|rsw1blSe{PX4xI(cXX^+wFVZFGkI#x z-wILxPVPRqE>FGJ? zGt-x+-<5uU`a|hYrT;u9XX@0cGpF7^bLP^eOP4Rbf9XR@pIZK-<@Yat=>Gfff9j!! z9((Muryl$HQ%@C@(xQ4=)JThFbJkL7Eu+>NT3o~x+i3ATT0EbYl=3B&w6v6#Hc+XY zO7*nNO3Ui04gY7;@)A{fDJ^fH<&CtWj<2j2D(BLwa$40$t7g-xIkdWnRyWe>CR$TP zYiem-6|HNeb@OO_Ev=ueYAB@*<+P!aHr8tz=W??fk|^=f6prv!l&|8bRfm~S0cdQ5 z781Th%~xn?MJQhq#$V0kEF3N1f~YE>vf>(Q(_KSBV8uaF!xvtms%j>54&i^KAy5A8oo*gB0MMfXe_RFR0(KhJ`klGIExifmq2(T&{!3xV$}*%((zRh{M0Dw z2NU%SrDltkH%HK{2p;R%Kn`!=d5enX=y^X~!dp1vM+%mmNqDQkxSpxwtr2`CD~ozn z9M>rDH7d&V6Uz~Y@PLo3HYNUl;Z`JTB8jK z4TD-ZUaJd_h}1_#$7q9KN@*w!qdFQ+@in4cC>O@*_>j=hurQrY7p{v4508jQ%}Fz- zS<=>|ZBOe?+mp68&6z(V-;#fC{`UOt{JjMhJZ*T^v~6$eZrf|`v~RcX-MoEs_vXEi zKKkgMNB2JJe02EmqX*Z_*^a_mnPCNG>JE)=W-}!L}1LN>C{YfOU%wW)h2r^>~!%@@5SQuqvBy14*lomt=VK_rj zbI5JXB|Ha&#)+)GIBP7ino-?U95J9g*Bndg7zWU*Pz%df*a4veq$${;)EvR+vlwc= z8Uy_V(xH@&A!~rG0=6`k6sD4rbcKISemJqllad6IpG0PkB{n0e0G?2Y-yynz)J-OJ z`Gg9E3X(0I)MXGs4H_k5Ndai2k&;YO0)f?F05r@BjS8cp4^~&rSYlD|Y9$Y_i;ZEiSiiRY3^Q#DsAi^84OFYNgmo;L zkxHyVohK?fzoJ#>tSNx_?}%_S42lF?K_b(qn(Hw5HP(?xI?y7VC7M_mBj#vgjv+IW z$qd#y<|u-nYY;f53sla5F~*X5W(=7>meh?W^E1etY;so~bW;&Q79|jC5~&zV7NwHA zOw0mshDDoVuZbzNnDGQ?sX1FLv1Os$ShcXy%+64N%M4JPIVyd9ZLmy%LC{!Piir#00;-!aKA`b9(wM`n zR8N}H0=zL<7#7naE1SzW8^d~oA~%aM4Je$M{1(1u+^Bw}Fvm1YnQCZ0>rt#b(7Nkl z>=aq)C3O)*$*E#E=r3woWk#&z3I)&t7c7@q2CZRKYY^iLjI2+v#uTnIW4^#Z3e(9< zmXV{_UO}?b^SBa}0F*<^f+|NF&E)?r6E>Tz#|Ww_!d0ocs!*;fjI-)6=FTLcTi1tD}&R5?n3Pl9CWIgVkZdd`B^- z3Yf_dvte<^V6ZfFJ1v(L&Sl}7Uw9KC`6_}hs{)kga`1@*&VrAT;ybQ+Twk!LNxqJ? zvw$@Q=E?sg*2$_0RthU%C6r2Wqe9>u_#Xu}9LgF~VT9IQ;joFtW-#(?tXPvmis>jH zI>MyPSwgr1aLeU@TMa2G_0Kt%G4WK?5rV0Qd;H*Cgc;Hzcj37LPyx^k)9W04RF5dr% zhw*+8d}8KRWE4&t( zsF;{opcWAggXqmxLLx{M(VL5jMjfsq`l4b#vc9NwT6i3ff}QF5+YJC ztBhze)HeW9PSlaAXcVtPmV#4FG^%i@rKpBzBGgg9sSQ+GG%Hv|J<*I&j{#0SRd7gA zLy%5mkWM4jOi-tx_-qoJnFtfWx+69-AsdmoM3bt<7xor41qsd%)MbT$3L91{(Zq)* z5WN-Roq}p%|Fxww*O zvcmH~84agVt3eqJr$|~{LlSb6rT_vd!qs6!EUpW1SPUs5)cCEN;@Mz6!q;mqo)auJ zH;B`O_DaYBWhMnP3GAx^wL=^~WPSjGKJABK*X744fu0o;EdhrLGInEuEO4l3qa>hS zeF+Gv)B+K)IMwLX;fTPV6{{-^QpQfsU%ZqVZ5(<_Db%9ad@00H>MCsr)P+4?06AcX zL}D6aQeZFW&yv7lCVqZJFEI|8ZAd{&kieLtc?p#LrC{NTv6V5)WXNT(OeG83%0L!c zkl6+)V?48lD`QQGN=aFuDfMNnDV40CL6!yWuq@bcWw1j(PF=A0EI&kF7UTyT*+8WY zf%Yncq!Bs{1!c4SV*)9I9r{^C3+9ARC3;&WiJg=P4sF$eQa03eL--E>2~x)X*iYF8 zf~*v=!AKNIv2XTgl|xcCq!4VQHPa%Bh`v17OxRTiaA1&1o0bRVDz70*w-U<(>eZJA zH>s5x_Dp)TYPQ@y8G^L8FKnEf4f+%_>Rh1-WQar4s z3av8c5tPZNK8meR6L99j# z=CO&Rx-KxzS2L?)y|OxB^Q4-|#d>9RP%ij>{5)3&<*J4_q3Tc&gu)foRYT9r!U?=Y z{#mAap5MYrH59H7k0AOQNa~L;0U3uiK^v=qT$wt|gEf#VDI$rOYtRJBpjQ)|h2ebi zvr)sk3{wkyQ2|IDi3y3v+M$L?p-={^5wK@{4Qf{=samEDR;sRu;AUbXBB))dqAobg z)S-5Ku?``10fQ9lpw&DbeiFAX$OgP${z~hD>aD8@G(lZ`V6>?V3`C?Zs6#l+0;Qla z#m4H`K*ZVtjx@jV!$HVtIhZKigk&5^Mg$tmi9G2%4-9(d2F27xA~wL(mD!;IO`sT30~@~BXwwk1G5GWRlpD%OOjdjzN(F7K zAvkfs;TOQE2*}&Nh`;$x|*gZ7{S)C2dD~&Q6{IJnRoLwC- z60Gr6qJZOO?7?)}P_#Q-r-GKU$UMwV2^ei=2kFcK9i^Ynfyj#e%t3px^(vXeBxPNA zPI-Vber(C#8Rx(xCWYtXYj~Mj!ts5Xb73u$bbvHrzZ;A77ir23&}qsealD!XWHKW- zo`_hXYj`#(G+}9-phW5koyy+?9Q>TI5JrL1NEGHpc+o;8XeIzMhlFWEu*Pn}_ot5^ zV??BhgtE1t*aVwb44`Q~iC}6G=jDQDMD+7u^Zp2Y>HY}h_eZd9^G7g?_#@MT5hy`1 z<9UIOM&<>qh0M<2lxQscgAgLjFH;IQfr~C6Q%O2wCfuJjE|66- zmReG2NgA!0M3WTSDJF1~Ksz8Y=i{Q_sU=)t46AD_>PmtC&XGiuI7H#VbBv*(9QVEY z8>Lt4SUMw>=`9vi6Jm{58`KOO5&$5Jhv`^b+4IRzu0s;N(ih>nPfO~xlf;P<2E7&;@F&M+&@ z>=zn}LtVO{zVZk>e{}v>S~s4~&!BU%>0Nm=-mfyoW;`6#Xp2Nd6G24{)v;y+l^MA- z8hEj>@NdK8M{QZxmy3s_vGIhPi55?%dI%dEYhbL#(vEa0uojL6)#yOuE9Rz{OdR#` zkZM9o4v^z$V-9OVKoTbc2Y$HG$*8Lh4ALf=3esa4X08&2g5fMvG%z*>@POfu!h(CA zR^?J7%EDO>-y0pr?8L~Lr^LuqmcmqKOhmsRaJf;~9e@S~Gz5SKT9{5}`iYDMkw!Dj zAA5A-fWP2h{P#?I@WDjTNZv3p7Y7En*F6EEVr=U%aFZ-(<=)5RQ6zErnMb<=M;F@kJ7{2y3(s(ndM~Vefth z_xXTw1KG}4_5e#CMIC;)ujj~-BQ05?ata1?q6bY3ayS%AOk74=SXm#Mn{))?*l&oJ3B(QH)DeikfjRBoK-`RlSsm}EsRy0LKs*HS=3pFZY6-+6u^wm( z#8rSV3&bOUza|Jr+!2WD;aaoMtMp3(aYnx?7zdrYK%CLX$+03Mqu)%S0UK`P`9Z9j zmS8sGZGkwe#vKr8r3f!0(E9Ld+4xU7&iIPlmZBT2YI~1J4!Xz#mTx z#G!%Wu|_4^5Cm0S&rMnY&Wc_uM1GJQ;04#<)CJozjK7Ecfku?z!jC zRQ_hHDlM`WTV~vN0kEgN>&$W5}Ho9%`Ew{AIZK$tr_}9F9S1w<^vUOo| z^TJViXus_n*00~N!hY+m_R)FJzzyS!WW0~ltQXY(ZQYQKZ2#JC6w6jjSg}>bC>66) z>ivAQu5sh#Y_~+?6R2wS7sYY<-i}4Es z7>g(36jV9U*CHlwxm4EEY<)ZiP--DBZRV z^G6${+qbhc$36HUOLN>q58*V-&T%_-U~&N z7fg$5c>W*%zIO;9JFMv(}fgvXMwIuhDOLdFyAcx>-+q(szlL={6+ z@kEFrLOKy}_!(&CUhL3 z__qD83B8HZ9hCl&(nxlhiLU49&pG->wg$j|#v=J2VDZ0$H(oOd95OC({)uyE7UD#f z8wvXi8W=m?NJb3wGrSCR5$ja;sx)ans>M}WE!H`N9}>K(OKOj1bUKnZagNya^9img z;kyWVlJer@F{(e3&d^6#C0K$z%|iB|H4|fuq#NOHQbm^5eVh!Fq1exdhO%rM7Q_@` z+GKxNqf*e++7yI9&>k_dh(hYi35fDk{cfH}G9wV#kHQ`X`C_6-IyE4(D<3EVuM>$# zVq=q*hGOBY;zcsnROj>Egy=Zk+iXo3pJqf)d!^v@P!*PMn!o3fBm3Um>-o|N6jlUpOvN$?m0;RgtN@bIV19vazymUfCZUrrdi#|vSLXG%q)2V^Zu%Sh-0F&aP%z!{J{}5 zX%+nNk3Q$fF~GtR4&(jZ7yeb?@Hv0D?L0?r?dQnAS$~>wKm+gf-2C6A+LYpNhdmR0 zUqa2;r766zY`ioqJ1-W-y9DfdL)bCWyrbEjOG^3$o( zv5n%}w(PWAvdk*lU!=C) zY&~Sv7B48?Up!P?QSw;H-%7Ge?wzOsc%O^5M!~R(@BRUNxuc{;Joi{!tZET~xiI`pN3|sxMWG zHI+4Y)$FeMZOx^cm&dt*&lz-MqT>b$jc6TlaNc%&dZ0&9gdZJu~aw zS?6cz>T~Mr>Q~kOxc+ecpX%lMgobGia~tk%c&y>I253Mt(MV1=Txy7E%x$b|T;907 z@rA};H-6SgXQ#|AoIQ8;>e)MHzcl;Tv;RJOWcHXj`EzRL+%{+PoTujW%sDyd%Q>34 z;@rZy4Re>xy>IT%=Kf-?Ywo$Zv}sIJZc}+vYm=j?yXpC+H=F*{^ktJUFKJ%xJlnjR z=dGEyZQh=FznJ&?d4HSdofk2G{QQFXHS-tGcg%lq{+{`-&Hvr}Pv&2muU%kRkh`FC z!Mp{_7IZGyxnSRdHx~S1!QU2qw?NxGwmGM{sJXHE*5-B1+nb+ib~gXA`A^N~ng^S8 z3sV-F7g`rKE?lzk?uA%_? zV+8BZLOw>NEA-NkX0(I!i)ydu?;Pi^kI`gL8|b}mxk|4EX=q>=8tARN3T_`IW8{0wP~wpY?_q_1u5fV5YFA=Gzm`Jgoh>5aBl9h!|j!TiZr)C>)Ln`tC|qYie0 zVCw|?N-)iK_@6K`0Xpv?4db|yW=8+!HPtYqXQ;tynbBimcqPq@{@VP}Mm^f-KNeb) zPeujlor5)TZ(pT1+Q^yp5*zXZ1z4vjy@p@K`k;ZYCK*}h4fgHPMmV}tjBeeVW?gTz z4Og`5SL^6baCTJwKlVS&>T&c%BY?>&1sav1NgoG*p)(d!Q@`M>l{nDYKnf1fN znKMU5;xm0dE}oFDaLw|=uQ=}A4|)FJyZ8(QRrLdv@$*F>{4x-p4}|9e;RS!F{t96? z7}b7;2zIWlW;de#npJ;A^fi$C1mTMap@C0wjN~s!GU+}>XhQf=ApIdiR{NPi_<=us zmS<~9<}lsPwU92nyYTKrx7>x7jcDvyh?hBNSh$P>olbu`Bmf(o2e88C_mvw&9&?9( zU*09aaoy*8^RQ=DCZg{vcMf?I*=+dX4UqDCi~kMq?0=K@G2l4+{oZna`ZsyBlMvUa zJZ2uvP!G%d?WjD)c10lXo$tvj3FNWSm+^A#6U;;N<)gJ&^X4LCo9{e?%(x~aB+OHK z+6)AhSxI6?%!QMOy=RQnZoFinp-%c;CvBFe9mC!z7FjzEz?Wcqr}Yl`{-fA2z&>Kr z05(f|?zv40dx>}oFW(^>fSs5R@V@pAdFk+hi=8XziDh!gv1PKJ5wamml*kV`6YUeF z?y@`Nk|R7dGyyEw;74{6Ptj#woGgpO%jCsxGS=`biyg=Y%bw!PyYK8c#!OSZ7a;DC zR#JJ+U*?XA&Y9u@`J*AHyz=O=bDpOdO2jUp=u`K}^M+rLBTM}3JsEq1N*PPt?78F|(lJWV=* z45zFgGCF?h703oFJ^740^{r>*_uhm8&LK0m=lBkq!S@~TO8RHz>Yiuig%~w-L&(C? zZ`e;CzekPaVf?gzm>PDE0aZkI!RW-#`Yw*zX7Pgj7% z!;K_5PkDEVZSrGpDf%r4WN1cw;%09$T`G@L)E)r)hW+3r^1VmFXA?B=yF6$hoSgEW zBCp5}FEO6-o*`}Wo3Jgk*D_=g&k~>3xmR9tY_GgpQA_N-06znnpO-_AmKdLxwMP}~ z?Eq6xyH}Ksozq)xli%?Zc@p5wUNdEyKRLWdeyoRK>-HX^*Tmr(UYtbAo(ZrwJEcYMXEPL>Jk3s|QPG;i(gw+YCvWqjSQ~z#Y z0!)_Yu)+p_YcCDXt&oZ&#?hyjwLRPXeim|dyP%eeRC`1F3WAgXW@w_cr1U2l7nEcc^}DSFidEIPF?$fwCq zR}Rp@E}QnEn#GL3OEo$53LAySsruL;rSEC^;T$>a z2re$k(MQ;viSg(tvWZFSA{lB|m-W53EJ;V+3P~F1>nLNjDwc2tC_BCXK}0aQ8KIr0 zr&q}JJuBq-Ftaodvb8R%R-fMK-A8!O0dMb*dNsUjr*|h=A#VcOCZJ{MakIMfo(|b_ zStXh62fSzW`wn)$Z(t%Iy{hd!hv4h^zFO1l#Y{b41#OMxe0 zMAbd1M8{nA+fwMWO7ie!Ry_7aBq9&-p1)p>#Q3ha{D*8{gYfGB6Om=i9*R7Azr1u% zv~QDdQtH>a6arIy%(y`Q43db}3Z56(@Zv^tk^K1Om%TcSb`qNl4o+h&srv#sg69VV zZSqq<6fYr}A>~PeCwovWWjUuKHg-@WErJ~`lCz-7SiJ^pWb-Z+41cj~J>su1R0LS? zWGWIwrz3$5Bv#5_z9o2;K}yih2at*_-$teho)OY4cMTWGuX?pk!Lw_)S^kDeUdPIL zqDMq2Ls}z0GE^&{L6xB`0INKv0j8bMrAlI+lF%^sWnzLUtX^&Vtnf$%|vEWA}As~~U05I`dErwvxgdNfP4 zTFU?#096fM89rhG%oN2%4DV{lKppzWOuGe_Tj~6^`2F@ z(MbmeM7?EuoRlJI6T?nhtYf4Oxq2{Fnhdd62h$^6c7#E#qo8IsEqw+u`onAFBf|pb zjn9VslkOV%kkUY=AthT=Nm3iUsg~^+y)7Pm!Pl{RLulrAA6YO4>5nnjHq1~A2`5GO zav53|H1JFzdI1J8a&J85(F7B9u>p+YWtyA;)a>&k#bc|MI(B2Zrj}COo8_+tw9a%# zvOB>>ChV46=Sg&@ojm;e^Hf|R&Gk+of?eYl$NA(_KD~37m$V4(G&_Uuwtm}phvCbE ze0Kjy4A+i_tQwcPgFlc9`8~y)xJI_4yN_(bDi`w`bI|WnIF3FFHg2#HBW*2e-Ozfx zl`)s}TL6hTsgg?i$qinkSZ>f43mF3^S!OqNBX{I*dW}HFNwprLQeV`o1sBc2fwL*w zmG9QuNq2YG%h15jZp26^5bj00v{GL0GhmkKvQ9kFX_|1ND1>-$V3az?Ycz9%@1#9T!k>ESOT`zO++e5UNpHuFb$q0?&t|7 zX#_pXuq+gOn*>)#fru7bBR}zGN1684a8jAU%;i108Tr}gJ!OK_?LC3j*c6OIhrBj& z$XlVue2oc0#1f42m69o)6|O_x)F@GElW!W_D2dBRx_GHmto^5Nt=J~?OPXJJP1II8 z%~eF|q!sc*z5|!PyVxnIE=P4fkDOaB*z|GGz~eKFpaT2E&SLv1g% zz#NCYERI4Hg`zA}f0~iy#%D^zxLAI8gps1+0gG{2@3%NWz0he9+wL-`bB>=xvp&Gn zpYXOYCeqL?YN^xlC$F&kqJwxMh0uOV&@|d#uRUb@#Cz%>oj@GNC0mb>rE$F?-#sWg zKk^c6>^i+eQP0c1L0q-z^J?1qUXj}eiK)f)JSJx|u!TN`*XI#31@Y ziGH`C}j++j;|s$o4smdcgxR&|)Ar{zJP(M=rpSyNmSE)W{!;kBg~h$_L= zSsLfU(j+9>{feA6;Biv%YFV|Lv9STnQa8g{SFY_?S6g83RmGit{UV8sb~$XF>w47@ zr&$dLecA5k13P9K$%ptkIQ`*J_d?qi zd8SX0EZ76Bkz0mEsBhu$TtL%(#Pqd`O%MhW&X5IZoBZk!%(<_{&SvU0a@8@GtxrTY z8q7sJe>p-tPh$*!k4pm#mVFCJ@022?d}+UI9&B=w3AbF(k`Na)MY{B+IM2gh%|kb@B7cU&G?4B}^mrma@w#^7 zJ%G0pZ+Ef_BM^}!YKrfRb%r}%k}vpbr5?bZmp>YKJrL$Y16yx05@$h|dsDLWr`|BK zUk>pS(cA$Wev0H=cD*eBct|ZhFTX#azD#5#lwOt}9+HZGVg2HR=jC?>UQ~!39e4qu zzp5j?m*vi(=j9g%UY6G=;SA@?^4&whI$o0h?4!mm7{u?+;u-?hs03%Fk7LmL4(Fgx zVnArZp=bA_A{puuNg?vQIGHR!I0G+F@3Kd*M%W|YJv2j`u4uv<<4P^tfU*@=2s^GBgB!&{8;ix6N4@3(j{=L`W+ zP)1h%1Yb`3EyTZ4E(fX!gC7a@`#(oV$LjKyXyY!9mx6q2Fs>-Hu`(F~za@7*@82#B@0j znJa93<#XRdfrd%Z9&#Ppldy#>=*WyWA8!HP?rpimg!6Kqu8GzAS30lA&ti*gNhfZS zew#eOr|-E z2JW$<7wo=gh5X*g?p7vQhvixM>7%#Foda~jM`y#uPtF#3I#>2%*wAlA?XO|{dQCA5 zrrO&-4z*0R2zfMaU1yUfyUa>6h%Ek+ETu;^LYbTrdJGb8$ZCY>w9aopMaEgz-L zQ1@Xn!94lgVDCYn{D$v#`R4-;=L)Q?4p_tbR><9#ElyS*^WTw2V0xW|*w3H!)4cs` zh=XM0xiTCy!b?@ovWWOIWxH;y(Eq-)0P`jNCqK23WBKuoLH6 zkM75yy$64&kklz8Ll{ZD)}-nqMy(I8}JFBax!gq>NW?1>2$)){t-r<2hB z&9rOfsk5JW*L=Fdlc3@QoZ5CK~?6LCrx&& zfXM?Zd(ft#Y$RNXuY!mUCl!#CHR|8ELZlccD#@~JrMzZ9Ag^E<;zB=pO1^i5#h#VV z52-F10MS5OF@w~|v=%i;l(1v~pZm3oOG<3G^J6bAf7aVbifrJ^eEi$asLkFv`bWJc z{bui6J+a?d)3R7U^%eQHffna<8$PmtsZn#kgZ$osCoQ(4_y z{DxkRMwxdAC&s(|eEtH%Sb+o$EGspVcKPstUyO5@2&SK9MGsuQT8v<)e2Taoq~{+U zRLnSwbEuJ>o0xx=(!Cmy=v%`HyZS-|bX}}xcVQ%)fh|H8!XwXUiOC*Lwj;h7FA1GS zcA;A{Hzw|P#Fock81%{E*ga)F4FDUho|B7)Uxw(^6w>FDLoXAP%C+YX|KLMBYmcxo z#r&RvtOGI`Az4}=4q&Y$xCD$W#!H=1Z0LCpW6BX!x=g81cL_x%m1hRVUF#5%(7>${ zjxnw{fq8?Mw{eq^V&f(Tdyj6*d=foiZ5EySG_{b3!5 zd_F+3bbSZphrP^e;**amT*Y0(6;J0cQqTpdcl&|w$cm7@J#wD6z!_otbUVIW+1o)h zZucfV92(CJSe&5@xLtpvDJ7pHhXLH$5d5RuU zsE0}S9}uL6VRFKY{KY!5QXV&$p-fC^Sn{Wym{_4K`k{eEWk!575gQ9Sev>81n&=u| zfs{V=-s2XE?UYzfP3f+<%usulEA>(*7uvE?zGYx+1-0AqqFSPoJG-`py*1X*mb0QM`A*e9*0sS#XjdNK+?aybe9t(HsY%2cton0>P z9U+*5Kl1jUW!r>A%$RJ;U`GpfY-DC*>55}BfeK@;Hk6=Setnr3(IOu_>UD{aXvk?Y z?rDw2^|#_jG^#$nBHGbyB_~J^#jwATg2Nc4b^^~)rE(kA$!%2POZxgjFsA0I_zkiKxE?I0UC>a_9U z#B(^Qw$QQFI?m_K`Jj}owK~huBMtl$;<#slntIB)Z36>Pv5|@|5!a~GCsu8`b zBZSE{!gZod_IY3JrUO1Bd072;xpSbr((zk6*Uv{s+aJ-4JFRPvc7Io{vm5POG-0Q- zneivy?tdE^Xe!5v3GLrNh5qB%d@PIEqS2iezR8YV;la0|_3KT-&wAlfAQNf#Ysq)I zM?}p5jP5&fF{!L{*$kG_hbADkWPNNP#SZQ7RtFDjj zeFuep8a2Tg-lEzPzTv)gg1hz-DGhHS6T&wIi;Rw0cB578dZRd|jqi(J8S1D{3GHAC{h61; z9{&7EX38G=IVxdx*(s5<4F?{U^lI+38tXgi{=JuUHD)VTe8XaQ8UA@tvTcCx<;+P&Dc5C1YKJxZMBA&IQR`;!jh&y~KBlMBP95d=#NnsV zKzWss+}>g+x)4S`UCgRlElWP`i6a-eNUlGGhG5IaN2>8x6{*2rb)?|Zx`m5T_^uxg zVG6?4SSP5|%Q$!AWcComM;XLX-s z;VkI^Yv_p@r{{L_1-Nt;3w`E}E+$|K?GO$Wu$9?U_!6X+B-ZFcH5pISUbK&sqLa5< z3~n|XmQ-UdFkx6RV5r=Jp@r?!9sw_mlPJe5XW#8cIJ5Q?_kngo#|!od$6YBA9hSTW zhK~-u;Mit8r!;xfA=H3{RM}wd1_{e(^-()~0NS)e}6H#R@)#cwlS(D5;i0u9_$W5ieQiWS&|XC%fn*W5eV;x8U%8Q;iEyGXK>UOX9! z!YS@B6l8~IFU$81O_qcgizF4Z2G8Eh_+|-7c=@eLt-G)}qdC-))R>CDsS1Sy)=MXQ z%JU>U1YLSLgpH(|c=`l)LJ{oSTQ*1sZ6tk~wAl{tHc3my!QTmVJ+$7?Q;&O@FNua} zOz|%5$Gb0bL}glf;*)d4qtiu1=t-3vt-lJbjIt{7PEXgO&@`*iRgDQ`@ zxa@-aZolbmMUQ&W`qz`%{!r)?%<4O(J^i7ysPvB?k8_g=pLn$!6Hv{=SE>o`+l7Ie zRm5sgyHX|27y==D@Z#8%7XR|#E{q)yTK|61EKQfX&ayg>C#Z`fi~ot%Pd#S{Ct(ui zqNqD;Z`&;nt{=WGd#{GN5~VYrk0=}C3UxBG@1@n7A@Ga#Wsc}%s4Rj?yc97g{PX7y zy*t*??1Wic+DbKjr*EHP6DB5 zG-5^+OAivUQ`#u0r43T8t+w1C_1eoFxR2kDkNdhtGF2EGMl!K!vs*OOP3%NNOx#B! zFlFzKL@4w%A2zs>ws@)Qtz@&iz|r}t#jwws{V|s%V4JAHb}`PC;&wPXQ&c9+2a$-y z!f`zguBJFsbe|Ch>yrmZEElxeq6?v+A;^z6sRQt@M$`}`BqRY-SVmHLO7%fa3C(^V zv^mh$g6??RacGY+?QOAW)b4TDq@e-xEQ|wSIQ&EM#H0(MB=v%p(&A`W>IF5KbRmRl zi*>GWH+drTLKx9rz&)R0p)cMNf|R-#zA$meS)ceI+ADNT3eG&nkEGgJVjU7Z5=)TS zO*@fdn=MVvU@8ZN{^>kdzuI9r=wGdzP^(Xkh`;&FKO8M%dx+!+*wRX8g<+#L?Bhia zZDyz|Bvb3MBw14043>ks5^DPDW1sl*&$5%rL^j?exHBD(I5B%*%^uMwIxHz0t)U;U zcAUp}!^8dr*B*o2&>_D!V8(p1-rzfU!0~|fvy&e~1C#2FW?8XXntmb*1$m+Z{er zN#95QKA1ioV}2J_H8<*28RotWjMH7#tdF0Bm%bY(znGObg}IH1m5#0JV=R>&8HrmQ zQ5G$_85@U;jty4NnJ1O*#Dw(^q2aDn$FIs;Ak>lpu}3?I&ps4WcRUs?4?Smr$c@vAmyAicpzt_ZiKQ>{5oemd!b zhK|S7LW?ypZ}NoZLYOAx0!L5@TK&b(ed0b$dq3l5;^zIe3M)GZWzjvhEz;I&6lPHr z_T$ghP*_z!VauVgih#n7Sj(WWc+-r&9|sh60~A)LC`_G^9#B~7H3~Cr{NGa;6}v5L zzDafbP*K*Oy!uyz%5fhj?lAY0(15WKUNWYqUn_c=j-FI|P*p;2IQVhLHT}f`CpJ?} z2pN9?R}70IT#;^ePGCU~thnG_=RQk*impLJFYr(tQ&ch(H5Q8coHiMiPH@YQrJE~y z4{ntx&I{@~`s`!^>zg@J_duAL+RwjA?lC(#69?xp4tCre9AGrP!RGSf=aL2}-DUm3 zUmljU!pu|iu=eoDKO5FaKGS3z15I}MAqz%)rb#Y3zEJX~=MDNy<6WP4g$*Q4dofm9 zD>Zr3M3&cG<}(>wJvbYJ1`M-}L~~-T!)qt*NH-hWI@dXzZHCVd3R&k*DsTmc4-&hQ zVX`TojhHUOkCpV1vBsiCL$%PR)Q*vML3>vJ(@BsSQuGk-wgW}xX0$6}>za_(^m z7*IAut(NzD-S$N1r;ZT1T7J$ewkJ9*-(&;68;%aKqoqS!$qG+>9fdWZTF`?#BB)1o z8Yw%mYoURJIq(w(ovv(U#D*f~sbJM4~@4xi}m==kaa7QzxE2{w?L{BsB&VCIU7J z*?arGIJ;@vkFCN7+cerf7E_%xdi3=8rj7Ou?cHU&+mCN6Qqm&Werd=ib>eJ+r#op| znlktl3#3a*kdmcvS4%rFg}GMAU;EUOdm9_dTG}&Es>{dY{1P+rCL$ITzl_z^gI=y~ zyq!;Nmn_n*GAgySLj&PWMv@8ilHu0&_u8Eb<9igwqXLX`3WNWSRkO58?(vzV-=hcI zd`aQXQzVcGEL=sGd)vD5-fuUMT(6$&{;s3dH$C39)0+m@aCBcwd#7`i{8OI>d@z2k zzLxe(DHpMy3@fYoqE&MDTYeXB6rjI=AMJHoGr`}-1k$?=l-08o`D@TE*UC3vR^h(J ze0kgDF6S*a(*LezzI@;1f>#&9;Psa*kuB{9yj3lsE>BL(2WBbSt)z#1+IdD&qsKzE zXs5jWs3V6W6D~nB0yTX}aPx-YNf#U30{ycZdq$lvZG1AP(=F6 zpg_*LaBMyf;;84#6E3&BnjH|w&cx~9U7j0s9~4MoZpRH2A>({E_@|l>7fXErmmg2DoCx7? zsjyV(9G<6cxv(7?7=Z>_Z#w0W7Y^#3Z{Q#@*>yxsPT!>;SAN`k;E_+arBodMb_1Q& z{E)>^9?>$kJY-Po(N5R4z}IIT>Jx8cZ0XGLFm>$>=p{?&Lzv>4%I%G zOB@d|A7O#P(em>6Tk_3|f|N90$$`8Xe-CTL(_fsxR@$v6p`T+S}$O)fuvK9p?7`f;UP ziBXuf%ocg=TU4AUuN^q#4I#v6mj67$;M8*yj`hq>2k3{U&Nk{qv+N$BlGdDR@AY!x zBK%d0savcYSOG0=zqFvpx<8=E%){hjh(MUnq?_wLg=wGQuZGa>LpZ{H*{daS*iLrg zl7jJ`5Ou<-SX11|$nwzCkYu-Eh5ReXtaG`sD2yHImcPS=gKl~3Ww*g6AM zkied5PkXNO0EA`}oeqL8dvmpIrToF*3%KaB%C@%^UM^t;Ab%QU=gmyrSq~`$*qy0( zX}8=vV(KB|lcX^cCyvMlFPl02M{^rx70^wuDdaZOP0Zm_O@~1ed>af6_ zfnvfDM)@`FL*U{r20qCJ#ihT5iOte8*H-e4o?>Fh(*Gs-?h&n1m;OUckt$5LJSmmy zhQ(J~w~5=>U5dYNeR^x_R&i^oJZJblXREx!*Xx7^zFvr(k+=faq}UQG*0opG4;0|e z$=$;$=_Ux*F}P@(ahpjhl@|=V*P5M??&$PdcX)cWJ0!i*Ev~!II|rANLx^d~Aum4Q zirLqF&wbvxMBKU;cVAlYw}L#1D=K^CZ9~Sbw6k?El7EE>;U)RaVF;t##C%B}JHmuww=!RnlSkZZUy?&d#=vf&Ssedp zfjw_{xojVZ!#SMT#qK5z6`AGV9Ycr_xJri)ny{YmlDvP|f(6D)@?*ot&OrkgZpMj; zCA3@*N+U;@l{0f?4Za0ewDcQAa_MWF{$P2u_&%yElbVr^RhCM(HG-=DgpIXJgw!oD zvs4YcoX6XbfBOy_mkc)@S&cbU7K6KPykVC$|<(eH5B=qVtHEx3zq?kHn%t(m3PA;mt-z#w`BG6??% zQRWYx?x#E-o*&6b>Ta2)(6~hINB=?1imbKA1 zV_=S$L}!LQLA0$rd6wNqDa7f^Ur&gr{Gnma&BDXO(;X~Fn`B;PvRlx7-|Q3DdR8)) zX!jAUj}Fk1Y`=;4*`CeV)>2a$@S-O&R=E?#d$){)@Q5kRHEfFN^Yi$RQTaM-kv_oYis4p|__;e7 z;O>wO{B;uhtGHJZ;$ZuNk6MicLcDuc(Prn{V10yo{H!Y)C+X-OLw=p#0W#RVo!H~} zP0Amz6^_=vhuvJvnLQ3JLw}Mp#h>|)fG{B^I8)>aeU9o3mlNg^azb4C9F4!lI`hw7 z)C~09rTzQa8|-F(Yv5$=0k5ia;#s$2@mk)5>%14$RO8|y!c>Tx3voHuSoi?{2|iiF zL|=!gQZOGI_L+W?Q#Mq9RzB zK$Hm(*Z|c&dl#T=A7So{m$?F9#QVv#Q)re+xyJpI7dw+Yco}yA8)?U6fii1 zvn#)E!59+9U+EZqvPB6@lug**nZfE>iSw4M5I5c)=EqM77b<7XeE4ZpIQ7axixF#D zyvO9AD#wRSsPe~s{f-%^vMD?ctl7h(1hEUum>Yvt@B7;5i2FW;RZn3@)jPtr!Pws- zHd5f*^nKGHNgKQEgImJA&75eaR*s$Tv+t%*9vaO9Vpt&g*^VFPZf5K%T5K=6ngnJ8@} z8go3T0owRZ#pT46hl@nGE&v0ktLzMl0*f%&gM-brBV(G~QD@G$#kFPLX4{6BYCCQg zal@b^!MaYLPm5)=__^hMeG|#_wc5R$IkY(sexcPE1 z>q$^;#gCL)B%3_{+AhOMFTs2op>C5PvE?PB-15ZyoN{-njA(5mpf z*3$iTEvixb8EQRYAv8GsL`NCf7T!M06S^Kw<}Wx=5dVqiwV!t@wO0d8dUPTn@}59+ zTK_g^Yr9KJ&qP_uuuxGKPDvF|`P@mo>#O0XkI-tkL92x9^1LSf6Etyc&=z+WL1g!A zv=Ks)9E2(P38t`B$wY}wid!}C20ZhOrl-scms_y9yMV6t3VHcSGD*~LO+L7PNR2+_D9g!T=twBacsAC8oFb) z6A2OxlcQV!@zmq?a(kIwcBj4U=FeD4L`gl-(tESh(3>KPl2Huxs#w zJQ~Yoj+~3bh)xSxy?lLK2_Lked!&?beib!2mnAaqRgRrQ*$Cq=jKwAcS2^Gq1sPLg zJ&M(MLo-WTqlav+8?{+O0!xY)6xV9UpueGyg7;(^1?A98GjOkQZY1)f8?MqW^cX>> zzCbO3!>(_8{h>ze$2v@L=b?yn^J5kVkulK|)YkQjvZQ&tbtq@aHJlaIDEv<=5X~#o z-W~X=I@|l<&5p@MY7&>bu`znsR=rV{MDJ0F=-@I9M}*=A?IfnbWSl9D^wnxQ6@fcZYVskM&Le6CBU4%QL zYda=~pwGoWXRS}pEDBd=HHZmvrj60#tiwWFX#WWzGYBT-ZmlOeY_5R`VOeHdAluI0p?ud6@sT8-wcct> zInRXTbE53mYN7Dg+~*C+aza)t_Hg6@4E%hxovqS}dWh271MxM&Gh;_k0jdZjz8rTa zvJ_}Hbo_fl3QZWLQvkq>oS8h==1K9~msM75gcQ!D>aY2@^DjnUk%Wn+@W(el7AzC^ z$h*-hwlKq&5ubbQ3oZ|8$9nG6V`VqxE(Va95sc#C7O`!w_9nzcdEk(6$#iLAIy!FD zKX}(%haB8eqrKUiD}T1GMw^8DZeGjT|{KicTZ zHd)V24K%q;7jnIM0D)jLu_cx3JFZZ?+7Ssa>$9&3U$_#p@-(C^T`ozbNg{u3hNaLBP6#rOZTJ(IB0)-SJ7s?lnDCgQy@x)cRpsx^1}v@dRR zkcSXGOSFpq0?d@_pyrR9_jn5+X8g{j8;>(F=#P7YC^UrhWhwhSbOOfJ0hi)T(p3 ztUgPSNCRg*0`Q^>QTCxV2W7B%uXYmz8Ga=nFGsZSk??Z+&D{UlAkFP{Y`6sqMf^~;J4*A zP=PsFt&_EfdYXZ#r7W$jX>9`psw>)-Y9dfs22}DoDmy5)MAcS{mT2m)=o{0(Hu-bd z5eWW6S})S_NSptC+ShJRM9VMH&iB*TU&7ZZm!D|0==MQWEkUo^gy0N9<94m0x6n%% zcxk;I>InY2;61)l*($$wo#UpLe%Lv{o!NZ&I?vVl36(RBA{C#P8oA4x3ca+UAl`>T zRqYNuCn%hpuZzdO5D@S@QGbp})MMVm)S3QgBpy#p?$A3oR&kv4&W&Q`@SUonz-F!s zq5k8pwG2`q4c%X|ZH{T-jPk59E~k=&oz!H0h2QRZv71S|>zmz%&tL53oCn;(=SGNS z)D<5N8Wei66gLH%>U~-VtO3|Vg2Q-$PR)45;$UZU{I*h?+;P)bB<5NpcF2dDB8fg% zR}fS=Fwo$Ko{>}`dnKA7s5dkO;p705&v!!o0wjdf7K)5ac(kMAkis%fN1E$~|A@363b~$e4_SJhhUSNgmK1&}1Uxr-}JfwBct zR&aSjBnZ7YSBA^2teEMoa8kIzdD14T7Orw7h1aQOJzQG(cE;5fQ1jem?|TKnz}{Lr zdrAB0z$71sb$No9TT`UM2;)lHz|`S41C2K6zo~M=llP4efw?T-{H_j{MaqO=ZP~X2 z8#u^VWXeU?wom3Hl0CMgM{MJU0K#)cDnurw5lHcCq@eY{6fQ&^QQHk?@Q~t*Ta)bF zF4>^$c~aW5X8VdHJn@zE>#j`1?{@w7WMu-uS6Jnu74ZK=?yqNFCB33m!{xo%Rgtp-q73GS(UZ8 z_`~a5RzvSiwIzDWNnul>DYlOEmT3Rv5ha!qDtHt37&6hflJ;w5aZn6Mf++$v=jz-H z*`iF6#>*3>SADIqN05{0yUkft#4O=aRokfkCFi_8+OLTO?hB+1(OUdtJQ1(0AU1=P&S@GXO zQxA?AhRmd%B!K7Q;2N+LCwdOztj>fz`x^rs%>#8C!6CsJ)j{oxfyXj(J!;EA=qBz& zRH9x$U3-uN&A%sTB&+?&IE3*&qba>j)bAL*s0quUhij>&&8YM=j z``B;HZImub|0eIL_N>)*-_F5YlC0j2G;VBs z$(!ygXU3<;m!xCl(b#ci{Q1gENB~S_)U6L{5A+8iY(x`Vp7$j!aNDDQ5qaQ?KF!|4 z#u^mL)u)XF6XBq?4{9<~**u5wBEH=q0s|W!vop^&ZQX5yLSi5%+-J`=Mhh`(cC_ro zeV!xkB2|fl^qQUoaTnh{s4awrgMnw_mM1c@{Y2BvI8*Q^3i(GExsM_=Ts_Bzg}6b_4lvVrbg{3 z2h2;fjnPY14VBw!ZTG-v?_Z>CV4P5;X7tP2j(!ehdK_iKDFDg@b_>cxrFp7<7-kGh zs85^S%Zak~lb*D;MC4i6;|R&x+bG{ok}a15*cV{VgL+P8ipL<^JWEH(+Wwv!SE!+~ zpPmdW%OWcQ9Z-mi8kEe{lD%DUlMSqxhGleqaK4dr+${yN*yezK=Ti~C_8HDzA*0^# zgg4X9;ZVdgf{pzw%2o*W&!WN*C{+#{`zYR}DWXri9Npkm9+}@YI|Yj0@gGJLnoj|G zG3p4+@A^#~R$M`W*h+h4wbvw_i}vxNngE5WKE6QqhT?8D`~NFJ!4A}FRY*P66Mpv) z)|_41x3@Vv#hfnj)o!r*_(~pHfMl(Ag+tL=t_4^gK9UJN7&SrX1}5-s z)xzV0nPsKBJtzXvEz<;@*fn z75(1i{6AMLIDN39r&<(XVA&I(h`NpJDJ>2>f}@+C)PB+*^ze3<=XD(OS)enTf*D5c zjrR%?WTZj`Aa2)dO9y63qzVyz9=ngO5*l{HJPFPL3`Yjl-yz^Fg0WVa$T~oXFj)4p z?VQXw7Gz{C51UU={5GkFQN=ik7Pnnm$_W9SMg#XA=R!Q9HxfN#AuDm9 zgJtawWJC?F!*0Wchew;n3ujCU3Avlb-#lx~60&(EzKzRb*%|Yo31SR}MtVQGZWwMZ znN%{ov4cB*=+4WD&v8Xk*nj~D`Ne~u` zT*Ea>_%!q5S71)b=v{!*oB;>Bs0+f^od6ka8;bq>0+C(6Lu9FVh7g(16|2JhXPVhq zxS;qEnN{f1p6CmL9W&4ay9a*Z*yw2mp5A_;HhIK$s;{2 z85H5@a_tY@>bn-4EX0w#dEB$n_$Hi9_(|^&a#GT>5IJ}|%1g_&NYAr40)|8w;_+5j zhKPO^Y@&k*u+A;A{lzKOJ(Uoq*YDQ<>{XNEm>oHy|B}PQ| z!c0jKza5zO;+%De5*+<()Pz|!!kR-Y|EX|m^b{2WAN>s#0wL$wZiQv7$#mT~Jh|8F z*SetW11jx#ZrnrK%7L`dGOaMm+Ss_(XbE!}jpyG(YFmiXS{2xvVE1_3$j!@&U@mRB z=I%X#5Dp8|zx#Z$YczPVH(2iwko}zgT`IHjXVvJppZ0j)kL5W+&$BsH3dI1~^V?`b z!*ZyWhuao@_ujNz8xIW3e-d&;4Q-@+AbSiyTCQdHEp9U$qt9OJakdd|sX#8hVkc0{ zAB2vex>TSesP3!4^-ffGxDuz3PG=1M$sqh3i$`@n9z@P3gUC6@sD*?BWRL-^&2!K@ zgT{))z3i6wm$yqSe_Pj@cl4g1^N)g?cSirfDzS>R^HaR~u)xGiy=iar9-P>};u-A} zjxEP@%AlvSN4wM=>qVd)q32e|S!CAWmAQs`nQustO^sgJjAu&&L}qAjSo)Nmd8K;E zs8@Pf|8dCELBPi*dn9dJHxJr{S;d6;9&5udseKN*K(JCv)wzuk;HY~zG(k9Pt`ZN0U!ceay~;t2R_Zsg*!F&kc`aO(Q8N45 zSwduRG<95_!CHcixL^F)$1)No{_ELo88xE~lYViQtS<=RVFwHcISdkL5geo{#VWrd zR(WPZnE7ClWI0%e$v(dM6C4Kq!LZs#i!o_r?g0j7Zv#D0-pz7E*#JD2Ma7U(%>>hV zE=N!d7<&_e*(bvAlnAChg)j=y$0CQ{co-3*b3##GukG)qk=Pn-9&GcL!8UKz+noB? zGVPVy=tnm9yi-t#)T;y6&eDsbW=f~w4&UP?%l!!y^r{@YRnBc2Y48x z3WvD-oba8B9Qvx-D#V>@jlKotB-5GJXp8Me{eH|UN1|_`It;_5d2m>?vXM%594-SU*<&D=dTI`BKtjPua|H(pl#=Ts%|%GO7vnQ|vHSKY$3>@Bst&)PX9tL7a?m zd`Ib!%`DFz9#Xn+bAx--*%fPE#P$WtjB*B=Eru*eduO#q9~FnibK#|XD`@vR8gwjIgnA1hc&e0qeMQj?6Dx9IBOkta7ItLw&nH` z7-V6p!aaloAzmHBrxZ_@rjLn}i}9xL26c=fy*N&qF={AS(0qqMRSXI0n1o_dsgmZx zMnpr@@L!-`Ml%k_bz0&e#n-_$C#XsSSr#h4#u9!5NCBitx;k`7-@x75?JS{lQ9?qe zV1bI$+2H8YXf*-zIPOk}YL7mJcTT~t^RMp;`Mxl086h)^6Pb(BO@T+2Vt$$H&UCw`IxhfiMCz zFrBH}80)pFt`_FV4UZ`0VP0T=H-k2C`Xx?Dfb9GJZVvry=$~prLVkQ0;Sjv%rDU?N zgfbn!V!=9b>Pif5!0bSR?A8gNpDmD`B^@mVpf{q=W6cpHcE~J3w}xiI$vf=e)ay)> z^zyklVFz`BOPZ>4U#4R1sRIuNTmKaZyc2<77)ev~z=`;c1@7bm2=yPInFjAbYT+NpuD zU>*%}V8Tvd01it<;`TA} znnEUq$*T%^QlULT6?|}!g#mn^M9=3`=_%i5-U@Bqz$pk~5(gsn0R;To_o?^N^i$HO zK6dMX6tk@|L8gGxPs*^v!fxCeNvk)Z!P0`dphLL$Ti#{^f{VXRvh|<_-Uj^x@0Yfh zTc)_aeQjkd*^r1>PwgCR5raN3I^)A{`z}rYtp3AW!3DcpDsPUlxl{|-p0*P7j5|kjP@!u+ zVY|`SSoTusOXb*ABXdI}4IEKXrb1feG|485k_7?;vmk%qWh7f6g3A9J3Z5N6@;#*} z9!H{LAmJi5xgLhd>Z@&1eKkd+`gsl@8Y1zr{D(!(3~rYa6{<#Jm^tDi^?0&`zY8HG zokT4E9D=y8wW5rGfy}3IO!YbPt1jJ8mNq4Z^f;8*45X(?l%GvDz>rVSMXe>`POarM zRUk=Ob?N_-K%xZL^iH<8Nbn_l3X&}GEicWO{`bmJSFr#ypjyDWp)wud79t*P1{Tl1 ze;(&Z0~&@!obq&8gc%`7e=I;*HWhURXHS*x#l~_y*oxU*L4QtHu*fM*$GB2;QJU27 zcWDq`Plq&m3>Wf&EXe|j4GfHW#?I(q;S{nu_`!Ts5VMwyau-=#PV8wr^!H#3e0BJp z(is%-;jd9b=kc7v{YsH3s7zS)R?r(u>35`x4x%OcL|ru6uGxtG6@k`SDtS z>#DhkmE%r)=0ea|-T1)55yeBtdcJk~w_mr0A=FVfz z_Ql#`?>XBa)Q){{50|I+I6m>-xbVQFp``+H=x1*cbIjN|IjxdTIX+rc^62w(!f%iX#8;q;^D~nWC zsmJXKPA+Rs?rc7SBr`%CEEVHp2Q*lnc zd(@xCw>5Uh(GKkkV@|3fTz4~DH=j`N=D%1t`g}{G!iiQuU8W!50O>h5cgY9~WyH>F zaNj&DT%V1Vk@-i4#`;_Vi&UuO_{PrLy%~D>f8ube0?xO;PTK}aR*R_mzl{1jn*B^n z00xrw*jZ;nf)V>s;d+t5gnN1*?uT);-XD5vAC8LRLxB`2Hg2t8s3t+==Mr|6Rv4Uu z9gfS@BW$Kf{+|y!&nI>%!P39jCXV)W@Bdg?onj z=U)Q`tb6TjXwLn389MtV`dxX}&vy!Z7CX|(2}fGKiR?BTAS7b*v$zV~e#28g!FQ65 z&jYp2Iqr_k#U^B~4>E-$m{~kAGD$lPE=e9ppE!&!68C=JF^9RMHQL^RBrG?J)9%+PT1PhY zA|~T-_fFpw{7%(>lkv&gff#%Wj2I6%>p{Lu_IjlO?dU+SR@?8y3Ao+sf}!JyK3WTe zeJE$WbcgtcrVWtn1`dwb;tPV^B0i{DU@|pf6J8DatAN)qw^c6yPC?mNWHz8Z+Lz-S zC3^ku+!(`Ud5dr|I*F@;{W3#Orcd-%Wa3Z_cV`wIu8F=6SJ{1atL)wcdr^?DHQI}6 zKML|2iZ|KPl2NKyMU>&zRMfT4)Yv{mzHu$u35E=p;7#IKs z4yDmtm*7Q?OMPsMMYraLtrp(ZR+jzHyaefu&Y)l%Ukf2PZam1*@oU3|@v9?471Q`t zVaxc8@T~DGBeN819uL`~Wf6liRZfsL$-9+S+`HsmiUA?B@)jT@M^2Qgu_JUOvzb~ zJk~E!rdH!C)ek7GxOY`AR9rV^4S(&%tUG?`E(#}I%FfF~&cpJ?g-7Jw5l+wZL{gQU zyo~U!yrPI*8J3?F7D)5D=UMQI^POQne|jWeNy{G--jhEyGC`T5ypEz?mh+UHYJ9GG ztnxbUm#Z_C92Bc+^=Ksr#j0A9uH>L9Rclj~*J}`7Geoh?%@1(-Ln1kNud0btUPo~+ zuQw?-5CCChtMryl9o8GQs4Pdb4WM`)_QIMwy1GkU+7>!Ryez5Zv z=5r^7oyw70iYu&4~uXP2!C6`CNS7IImuf; zr)uwV3WSImH10Q7cEgSo1n6`D zLK3Jde8Iv`k8Mtz_ceqquPoM4iqhR&4f+3!<4WbC2<6MsX3IOxHX3vg(Dh;kwH}yzG;= z7H6ghT^V18)e~L7Nz4XvkZVPrw4S76^64;73}bN{I8Al)$!HVviO z+PvO-Aemau zl+<#Zt*SOh!WSQ7QXjS{CnXzt*TP89NuW}xz$V4$Nt0Q&h-ac))1+VD3i@r})SiO{ z(6)^MP1``1T*Bh`iLfUDAY2%UB9A-%SAJ8t{ zi22t;zLfIG`7WP~CG>G4OZ5tJD#S@hNOHZ_((eqFgy@+Ts`c74zsg33S0nV+KbX;* zy7ttR2lNcAb2$%}?FdwaEJz-?4eg4puB~~HrXwN)GPv3Ta~eUmUi%O>5R=0{Tg{+OOg=8Z z-Vd!?Lu64@7+-`dQ;w53NOeD{J>DG?;q)tdE~({BI13sZUauYQ;XFgp3-h(s?!y7s zw|BW06n9*&6V}79brS3}IszT0#Pe)I{H1*DD$FCqQ4#fihw}z-5FCC|r6tt7^u66~ z0fkNlBSl0LW4S9|nh1LBf=C*I4RhS{VB(|>*M6b1Ij#a_d!ZZrug&$L<^Y*ytnGuc zi_HuZI5w^xPwTb&dT{>3NMUSMA3Rcs)EW(Qz5;oe)`YAl(fR)7v{1hGPr$%eFW6Z( ziNSIDO4z}*A_@()FQd)DBo8UlDDQs#Zio5aaII|Wv@i%nyLZk=j?AtH|G(1;q)vdE zTAs%~%IaLNrS}(l=G>UYMky4pXhvql2>I;P+wiT3Bk`fwe98efY8Fl^s{>7)7GZZr zQBaHuTUG~hJug6wu;=!i8{3&A-LEC~L#`Zb5l+e1_VrLXTu_>)F8KCs(x+DIIDKD0 zhR+FkghZN3aZ>Mp7%VcMvo%g$9pXHPdwCt3%0U8FDhbNjzL^@Eqwim{^Xn*RWFP zfN(5<$L39AMy&jdn)< zXpmT_IBj4rswx7=6%8Q9OJ^u*>j#XH2O2<36Mj!|8rz@-7K50x|HZ%>)$Cs}M*e0H z$KoGpVe{0T_$0ZT0mQm!7suXH_aJAo+6_ot`wM3Ffcgz`*8RWVz7H9#+>;nd9|Tw#HmD zTc#dHnRUy|TylzkI>mXToiK3bCCr56um*{TY;sXRKBAJR8bF5bn{8%G)wfUxa!&)u zu#P(^&LMn&ywU)2hifYQjH;_qbTZcrNa|Z}7}!f{9#WC38bF5o#|i9N^>-*dd8#pS z0@>+BK-%d=Bp%L`?`tsP)cpqbvib%RlNTGrNtYHH*ehx!8k$_#05URIV_*l>&w)|$ zT?0r)`NNcIE3od3K}KDupj0!dtpLF%byKNa^60{4X0}BA5j6)%)&BNJfuYzVw;rQVH8DPN@0{*p|P7pQSa z{~Z`O^<&V4$rGgC8`(y60`Nj^bPzSaWUQGCOCibXmLL-se8^kGTxRZv~ zIiP?%-T*RNm?^M*Y7>ox7{t?1K#-^K^@bQ^&c~1N?3nr=C?R~*00X}|hKMQQT-lfTv3?LN~+(x!l9gTd*iwqzO z`sPsonu(&50~tUTW{U=PSiOJ}l5jjA_pQ|-UjRaq?HJr7T8)534W}SdnjUP4wG{$L za@s_@kj2em1N!-v|9ETDD*Q@Z3K zm;8fo-Y3WoV2T6+5ocM+FZ5Kv0y(q+WckjKJo~wN1Vf#?*Z?Axy9}&JJp=?W2I7!!8$e`R35uxRK!x>F z4KBG_K%7=J899^78^l??^DNJPs)|TOJV`*-sAp(#7f~7VfPq7Wi^&O7= zQk9S^?U?|nNifr7B_h{~Sgz};rdu%2UPi98nL(WORSyVkueud+Bw*m3L$JuC2lxvS z(4a<85!yE(YHjm_0^6frL}K!t1IUKc`9}7n`a67*9OwYDF_=dvdIIBs{O16&Y0(iH zut$&&`Njd{hr_CA0`Vdra*qSZV^{rV_K-fpnq!d1cdnu}Dg(tL=QxNHSTu>T->QZ9 zRyYRPtV||I4-i7GaS-Q;zT+G_u11kcjX}2b>B#TLx5ya|;%u!tMa}VhK*$>oAWv4b zQYr-{Eboi|*{fj8A)p@%MxQW%zt~9mpMDLD!~fs^aOlcL;dNcmqyy=F+CRK^4zNcb zUq1EDsdqkDGvaafX2-#Tu#3PJN+_<@BQ{@WW zH*JXB(pw1PzgW0F2 q6>zuV0$Wdq;ims}A>P98UU2^|zZ5)E+VB26btY(Q{Qd8{c>fm;(0Z5v literal 0 HcmV?d00001 From cf1c131f738d66c7648885e5096668ddd11b886a Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:01:25 +1000 Subject: [PATCH 0144/1299] extmod: Add network-level class binding to cyw43 driver. --- extmod/network_cyw43.c | 460 +++++++++++++++++++++++++++++++++++++++++ extmod/network_cyw43.h | 31 +++ 2 files changed, 491 insertions(+) create mode 100644 extmod/network_cyw43.c create mode 100644 extmod/network_cyw43.h diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c new file mode 100644 index 0000000000000..fe73b07153ebb --- /dev/null +++ b/extmod/network_cyw43.c @@ -0,0 +1,460 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include "py/runtime.h" +#include "py/objstr.h" +#include "py/mphal.h" + +#if MICROPY_PY_NETWORK_CYW43 + +#include "lwip/netif.h" +#include "drivers/cyw43/cyw43.h" +#include "extmod/network_cyw43.h" +#include "modnetwork.h" + +typedef struct _network_cyw43_obj_t { + mp_obj_base_t base; + cyw43_t *cyw; + int itf; +} network_cyw43_obj_t; + +STATIC const network_cyw43_obj_t network_cyw43_wl0 = { { &mp_network_cyw43_type }, &cyw43_state, 0 }; +STATIC const network_cyw43_obj_t network_cyw43_wl1 = { { &mp_network_cyw43_type }, &cyw43_state, 1 }; + +STATIC void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); + struct netif *netif = &self->cyw->netif[self->itf]; + int status = cyw43_tcpip_link_status(self->cyw, self->itf); + const char *status_str; + if (status == CYW43_LINK_DOWN) { + status_str = "down"; + } else if (status == CYW43_LINK_JOIN || status == CYW43_LINK_NOIP) { + status_str = "join"; + } else if (status == CYW43_LINK_UP) { + status_str = "up"; + } else if (status == CYW43_LINK_NONET) { + status_str = "nonet"; + } else if (status == CYW43_LINK_BADAUTH) { + status_str = "badauth"; + } else { + status_str = "fail"; + } + mp_printf(print, "", + self->itf == 0 ? "STA" : "AP", + status_str, + netif->ip_addr.addr & 0xff, + netif->ip_addr.addr >> 8 & 0xff, + netif->ip_addr.addr >> 16 & 0xff, + netif->ip_addr.addr >> 24 + ); +} + +STATIC mp_obj_t network_cyw43_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + if (n_args == 0 || mp_obj_get_int(args[0]) == 0) { + return MP_OBJ_FROM_PTR(&network_cyw43_wl0); + } else { + return MP_OBJ_FROM_PTR(&network_cyw43_wl1); + } +} + +STATIC mp_obj_t network_cyw43_send_ethernet(mp_obj_t self_in, mp_obj_t buf_in) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t buf; + mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ); + int ret = cyw43_send_ethernet(self->cyw, self->itf, buf.len, buf.buf, false); + if (ret) { + mp_raise_OSError(-ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_cyw43_send_ethernet_obj, network_cyw43_send_ethernet); + +STATIC mp_obj_t network_cyw43_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t buf_in) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t buf; + mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ | MP_BUFFER_WRITE); + cyw43_ioctl(self->cyw, mp_obj_get_int(cmd_in), buf.len, buf.buf, self->itf); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(network_cyw43_ioctl_obj, network_cyw43_ioctl); + +/*******************************************************************************/ +// network API + +STATIC mp_obj_t network_cyw43_deinit(mp_obj_t self_in) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); + cyw43_deinit(self->cyw); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_deinit_obj, network_cyw43_deinit); + +STATIC mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (n_args == 1) { + return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf)); + } else { + cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1])); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_active_obj, 1, 2, network_cyw43_active); + +STATIC int network_cyw43_scan_cb(void *env, const cyw43_ev_scan_result_t *res) { + mp_obj_t list = MP_OBJ_FROM_PTR(env); + + // Search for existing BSSID to remove duplicates + bool found = false; + size_t len; + mp_obj_t *items; + mp_obj_get_array(list, &len, &items); + for (size_t i = 0; i < len; ++i) { + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(items[i]); + if (memcmp(res->bssid, ((mp_obj_str_t*)MP_OBJ_TO_PTR(t->items[1]))->data, sizeof(res->bssid)) == 0) { + if (res->rssi > MP_OBJ_SMALL_INT_VALUE(t->items[3])) { + t->items[3] = MP_OBJ_NEW_SMALL_INT(res->rssi); + } + t->items[5] = MP_OBJ_NEW_SMALL_INT(MP_OBJ_SMALL_INT_VALUE(t->items[5]) + 1); + found = true; + break; + } + } + + // Add to list of results if wanted + if (!found) { + mp_obj_t tuple[6] = { + mp_obj_new_bytes(res->ssid, res->ssid_len), + mp_obj_new_bytes(res->bssid, sizeof(res->bssid)), + MP_OBJ_NEW_SMALL_INT(res->channel), + MP_OBJ_NEW_SMALL_INT(res->rssi), + MP_OBJ_NEW_SMALL_INT(res->auth_mode), + //mp_const_false, // hidden + MP_OBJ_NEW_SMALL_INT(1), // N + }; + mp_obj_list_append(list, mp_obj_new_tuple(6, tuple)); + } + + return 0; // continue scan +} + +STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_passive, ARG_essid, ARG_bssid }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_passive, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_essid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + }; + + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + cyw43_wifi_scan_options_t opts; + opts.scan_type = args[ARG_passive].u_bool ? 1 : 0; + if (args[ARG_essid].u_obj == mp_const_none) { + opts.ssid_len = 0; + } else { + mp_buffer_info_t ssid; + mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ); + opts.ssid_len = MIN(ssid.len, sizeof(opts.ssid)); + memcpy(opts.ssid, ssid.buf, opts.ssid_len); + } + if (args[ARG_bssid].u_obj == mp_const_none) { + memset(opts.bssid, 0xff, sizeof(opts.bssid)); + } else { + mp_buffer_info_t bssid; + mp_get_buffer_raise(args[ARG_bssid].u_obj, &bssid, MP_BUFFER_READ); + memcpy(opts.bssid, bssid.buf, sizeof(opts.bssid)); + } + + mp_obj_t res = mp_obj_new_list(0, NULL); + int scan_res = cyw43_wifi_scan(self->cyw, &opts, MP_OBJ_TO_PTR(res), network_cyw43_scan_cb); + + if (scan_res < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "STA must be active")); + } + + // Wait for scan to finish, with a 10s timeout + uint32_t start = mp_hal_ticks_ms(); + while (cyw43_wifi_scan_active(self->cyw) && mp_hal_ticks_ms() - start < 10000) { + MICROPY_EVENT_POLL_HOOK + } + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_scan_obj, 1, network_cyw43_scan); + +STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_essid, ARG_key, ARG_auth, ARG_bssid, ARG_channel }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_key, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t ssid; + mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ); + mp_buffer_info_t key; + key.buf = NULL; + if (args[ARG_key].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_key].u_obj, &key, MP_BUFFER_READ); + } + mp_buffer_info_t bssid; + bssid.buf = NULL; + if (args[ARG_bssid].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_bssid].u_obj, &bssid, MP_BUFFER_READ); + if (bssid.len != 6) { + mp_raise_ValueError(NULL); + } + } + int ret = cyw43_wifi_join(self->cyw, ssid.len, ssid.buf, key.len, key.buf, args[ARG_auth].u_int, bssid.buf, args[ARG_channel].u_int); + if (ret != 0) { + mp_raise_OSError(ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_connect_obj, 1, network_cyw43_connect); + +STATIC mp_obj_t network_cyw43_disconnect(mp_obj_t self_in) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); + cyw43_wifi_leave(self->cyw, self->itf); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_disconnect_obj, network_cyw43_disconnect); + +STATIC mp_obj_t network_cyw43_isconnected(mp_obj_t self_in) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf) == 3); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_isconnected_obj, network_cyw43_isconnected); + +STATIC mp_obj_t network_cyw43_ifconfig(size_t n_args, const mp_obj_t *args) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); + return mod_network_nic_ifconfig(&self->cyw->netif[self->itf], n_args - 1, args + 1); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_ifconfig_obj, 1, 2, network_cyw43_ifconfig); + +STATIC mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); + (void)self; + + if (n_args == 1) { + // no arguments: return link status + return MP_OBJ_NEW_SMALL_INT(cyw43_tcpip_link_status(self->cyw, self->itf)); + } + + // one argument: return status based on query parameter + switch (mp_obj_str_get_qstr(args[1])) { + case MP_QSTR_stations: { + // return list of connected stations + if (self->itf != CYW43_ITF_AP) { + mp_raise_ValueError("AP required"); + } + int num_stas; + uint8_t macs[32 * 6]; + cyw43_wifi_ap_get_stas(self->cyw, &num_stas, macs); + mp_obj_t list = mp_obj_new_list(num_stas, NULL); + for (int i = 0; i < num_stas; ++i) { + mp_obj_t tuple[1] = { + mp_obj_new_bytes(&macs[i * 6], 6), + }; + ((mp_obj_list_t*)MP_OBJ_TO_PTR(list))->items[i] = mp_obj_new_tuple(1, tuple); + } + return list; + } + } + + mp_raise_ValueError("unknown status param"); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_status_obj, 1, 2, network_cyw43_status); + +static inline uint32_t nw_get_le32(const uint8_t *buf) { + return buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24; +} + +static inline void nw_put_le32(uint8_t *buf, uint32_t x) { + buf[0] = x; + buf[1] = x >> 8; + buf[2] = x >> 16; + buf[3] = x >> 24; +} + +STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if (kwargs->used == 0) { + // Get config value + if (n_args != 2) { + mp_raise_TypeError("must query one param"); + } + + switch (mp_obj_str_get_qstr(args[1])) { + case MP_QSTR_antenna: { + uint8_t buf[4]; + cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_ANTDIV, 4, buf, self->itf); + return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf)); + } + case MP_QSTR_channel: { + uint8_t buf[4]; + cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_CHANNEL, 4, buf, self->itf); + return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf)); + } + case MP_QSTR_essid: { + if (self->itf == CYW43_ITF_STA) { + uint8_t buf[36]; + cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_SSID, 36, buf, self->itf); + return mp_obj_new_str((const char*)buf + 4, nw_get_le32(buf)); + } else { + size_t len; + const uint8_t *buf; + cyw43_wifi_ap_get_ssid(self->cyw, &len, &buf); + return mp_obj_new_str((const char*)buf, len); + } + } + case MP_QSTR_mac: { + uint8_t buf[6]; + cyw43_wifi_get_mac(self->cyw, self->itf, buf); + return mp_obj_new_bytes(buf, 6); + } + case MP_QSTR_txpower: { + uint8_t buf[13]; + memcpy(buf, "qtxpower\x00\x00\x00\x00\x00", 13); + cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_VAR, 13, buf, self->itf); + return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf) / 4); + } + default: + mp_raise_ValueError("unknown config param"); + } + } else { + // Set config value(s) + if (n_args != 1) { + mp_raise_TypeError("can't specify pos and kw args"); + } + + for (size_t i = 0; i < kwargs->alloc; ++i) { + if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { + mp_map_elem_t *e = &kwargs->table[i]; + switch (mp_obj_str_get_qstr(e->key)) { + case MP_QSTR_antenna: { + uint8_t buf[4]; + nw_put_le32(buf, mp_obj_get_int(e->value)); + cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_ANTDIV, 4, buf, self->itf); + break; + } + case MP_QSTR_channel: { + cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value)); + break; + } + case MP_QSTR_essid: { + size_t len; + const char *str = mp_obj_str_get_data(e->value, &len); + cyw43_wifi_ap_set_ssid(self->cyw, len, (const uint8_t*)str); + break; + } + case MP_QSTR_monitor: { + mp_int_t value = mp_obj_get_int(e->value); + uint8_t buf[9 + 4]; + memcpy(buf, "allmulti\x00", 9); + nw_put_le32(buf + 9, value); + cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf); + nw_put_le32(buf, value); + cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_MONITOR, 4, buf, self->itf); + if (value) { + self->cyw->trace_flags |= CYW43_TRACE_MAC; + } else { + self->cyw->trace_flags &= ~CYW43_TRACE_MAC; + } + break; + } + case MP_QSTR_password: { + size_t len; + const char *str = mp_obj_str_get_data(e->value, &len); + cyw43_wifi_ap_set_password(self->cyw, len, (const uint8_t*)str); + break; + } + case MP_QSTR_pm: { + cyw43_wifi_pm(self->cyw, mp_obj_get_int(e->value)); + break; + } + case MP_QSTR_trace: { + self->cyw->trace_flags = mp_obj_get_int(e->value); + break; + } + case MP_QSTR_txpower: { + mp_int_t dbm = mp_obj_get_int(e->value); + uint8_t buf[9 + 4]; + memcpy(buf, "qtxpower\x00", 9); + nw_put_le32(buf + 9, dbm * 4); + cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf); + break; + } + default: + mp_raise_ValueError("unknown config param"); + } + } + } + + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_config_obj, 1, network_cyw43_config); + +/*******************************************************************************/ +// class bindings + +STATIC const mp_rom_map_elem_t network_cyw43_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_send_ethernet), MP_ROM_PTR(&network_cyw43_send_ethernet_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_cyw43_ioctl_obj) }, + + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_cyw43_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_cyw43_active_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_cyw43_scan_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_cyw43_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_cyw43_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_cyw43_isconnected_obj) }, + { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_cyw43_ifconfig_obj) }, + { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_cyw43_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_cyw43_config_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(network_cyw43_locals_dict, network_cyw43_locals_dict_table); + +const mp_obj_type_t mp_network_cyw43_type = { + { &mp_type_type }, + .name = MP_QSTR_CYW43, + .print = network_cyw43_print, + .make_new = network_cyw43_make_new, + .locals_dict = (mp_obj_dict_t*)&network_cyw43_locals_dict, +}; + +#endif // MICROPY_PY_NETWORK_CYW43 diff --git a/extmod/network_cyw43.h b/extmod/network_cyw43.h new file mode 100644 index 0000000000000..4228bf6e8f91a --- /dev/null +++ b/extmod/network_cyw43.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H +#define MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H + +extern const mp_obj_type_t mp_network_cyw43_type; + +#endif // MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H From 345e9864aac03693eec6cddd09a0dcd47df9c453 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:06:25 +1000 Subject: [PATCH 0145/1299] stm32/modpyb: Add pyb.country() function to set the country. To be used for peripherals (like radio) that must be location aware. --- ports/stm32/factoryreset.c | 1 + ports/stm32/modpyb.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/ports/stm32/factoryreset.c b/ports/stm32/factoryreset.c index 6b0c289a789b6..24e0ff88cfbf5 100644 --- a/ports/stm32/factoryreset.c +++ b/ports/stm32/factoryreset.c @@ -35,6 +35,7 @@ static const char fresh_boot_py[] = "\r\n" "import machine\r\n" "import pyb\r\n" +"pyb.country('US') # ISO 3166-1 Alpha-2 code, eg US, GB, DE, AU\r\n" "#pyb.main('main.py') # main script to run after this one\r\n" #if MICROPY_HW_ENABLE_USB "#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n" diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index 85c6ee1381b4f..c3e60caebb15b 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -56,6 +56,8 @@ #include "extmod/vfs.h" #include "extmod/utime_mphal.h" +char pyb_country_code[2]; + STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) { pyb_hard_fault_debug = mp_obj_is_true(value); return mp_const_none; @@ -112,6 +114,22 @@ STATIC mp_obj_t pyb_repl_uart(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart); +STATIC mp_obj_t pyb_country(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + return mp_obj_new_str(pyb_country_code, 2); + } else { + size_t len; + const char *str = mp_obj_str_get_data(args[0], &len); + if (len != 2) { + mp_raise_ValueError(NULL); + } + pyb_country_code[0] = str[0]; + pyb_country_code[1] = str[1]; + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_country_obj, 0, 1, pyb_country); + STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) }, @@ -139,6 +157,7 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&pyb_main_obj) }, { MP_ROM_QSTR(MP_QSTR_repl_uart), MP_ROM_PTR(&pyb_repl_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&pyb_country_obj) }, #if MICROPY_HW_ENABLE_USB { MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) }, From 10e173aaeadd589653fda89da34766322b77059d Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:08:11 +1000 Subject: [PATCH 0146/1299] stm32/extint: Add extint_set() function for internal C access to EXTI. --- ports/stm32/extint.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 59b20d5bd9242..1f147d42dc995 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -297,6 +297,53 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_ } } +void extint_set(const pin_obj_t *pin, uint32_t mode) { + uint32_t line = pin->pin; + + mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; + + extint_disable(line); + + *cb = MP_OBJ_SENTINEL; + + pyb_extint_mode[line] = (mode & 0x00010000) ? // GPIO_MODE_IT == 0x00010000 + EXTI_Mode_Interrupt : EXTI_Mode_Event; + + { + // Configure and enable the callback + + pyb_extint_hard_irq[line] = 1; + pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); + + // Route the GPIO to EXTI + __HAL_RCC_SYSCFG_CLK_ENABLE(); + SYSCFG->EXTICR[line >> 2] = + (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) + | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); + + // Enable or disable the rising detector + if ((mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING) { + EXTI_RTSR |= 1 << line; + } else { + EXTI_RTSR &= ~(1 << line); + } + + // Enable or disable the falling detector + if ((mode & GPIO_MODE_IT_FALLING) == GPIO_MODE_IT_FALLING) { + EXTI_FTSR |= 1 << line; + } else { + EXTI_FTSR &= ~(1 << line); + } + + // Configure the NVIC + NVIC_SetPriority(IRQn_NONNEG(nvic_irq_channel[line]), IRQ_PRI_EXTINT); + HAL_NVIC_EnableIRQ(nvic_irq_channel[line]); + + // Enable the interrupt + extint_enable(line); + } +} + void extint_enable(uint line) { if (line >= EXTI_NUM_VECTORS) { return; @@ -552,6 +599,9 @@ const mp_obj_type_t extint_type = { void extint_init0(void) { for (int i = 0; i < PYB_EXTI_NUM_VECTORS; i++) { + if (MP_STATE_PORT(pyb_extint_callback)[i] == MP_OBJ_SENTINEL) { + continue; + } MP_STATE_PORT(pyb_extint_callback)[i] = mp_const_none; pyb_extint_mode[i] = EXTI_Mode_Interrupt; } From 370a8116c4348a849c2dafb2c90fa5ba12b8c5dc Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:08:40 +1000 Subject: [PATCH 0147/1299] stm32/mphalport: Add support for having MAC in OTP region. --- ports/stm32/mphalport.c | 32 ++++++++++++++++++++++++++++++++ ports/stm32/mphalport.h | 1 + 2 files changed, 33 insertions(+) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index c770b62d2e045..f4ae7293c80a9 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -151,7 +151,30 @@ void mp_hal_pin_config_speed(mp_hal_pin_obj_t pin_obj, uint32_t speed) { gpio->OSPEEDR = (gpio->OSPEEDR & ~(3 << (2 * pin))) | (speed << (2 * pin)); } +/*******************************************************************************/ +// MAC address + +typedef struct _pyb_otp_t { + uint16_t series; + uint16_t rev; + uint8_t mac[6]; +} pyb_otp_t; + +#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) +#define OTP_ADDR (0x1ff079e0) +#else +#define OTP_ADDR (0x1ff0f3c0) +#endif +#define OTP ((pyb_otp_t*)OTP_ADDR) + MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { + // Check if OTP region has a valid MAC address, and use it if it does + if (OTP->series == 0x00d1 && OTP->mac[0] == 'H' && OTP->mac[1] == 'J' && OTP->mac[2] == '0') { + memcpy(buf, OTP->mac, 6); + buf[5] += idx; + return; + } + // Generate a random locally administered MAC address (LAA) uint8_t *id = (uint8_t *)MP_HAL_UNIQUE_ID_ADDRESS; buf[0] = 0x02; // LAA range @@ -161,3 +184,12 @@ MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { buf[4] = id[2]; buf[5] = (id[0] << 2) | idx; } + +void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { + static const char hexchr[16] = "0123456789ABCDEF"; + uint8_t mac[6]; + mp_hal_get_mac(idx, mac); + for (; chr_len; ++chr_off, --chr_len) { + *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf]; + } +} diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index d828bb9dd4983..0c163fbf85373 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -88,3 +88,4 @@ enum { }; void mp_hal_get_mac(int idx, uint8_t buf[6]); +void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest); From 12ed6f91eeb1d338713b8ec189f6b0110a27dff0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:09:03 +1000 Subject: [PATCH 0148/1299] stm32: Add low-level SDIO interface for cyw43 driver. --- ports/stm32/sdio.c | 353 +++++++++++++++++++++++++++++++++++++++++++++ ports/stm32/sdio.h | 38 +++++ 2 files changed, 391 insertions(+) create mode 100644 ports/stm32/sdio.c create mode 100644 ports/stm32/sdio.h diff --git a/ports/stm32/sdio.c b/ports/stm32/sdio.c new file mode 100644 index 0000000000000..df4aec25e2ee2 --- /dev/null +++ b/ports/stm32/sdio.c @@ -0,0 +1,353 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/mperrno.h" +#include "py/mphal.h" +#include "genhdr/pins.h" +#include "pendsv.h" +#include "sdio.h" + +#if MICROPY_PY_NETWORK_CYW43 + +#define DEFAULT_MASK (0) + +enum { + SDMMC_IRQ_STATE_DONE, + SDMMC_IRQ_STATE_CMD_DONE, + SDMMC_IRQ_STATE_CMD_DATA_PENDING, +}; + +static volatile int sdmmc_irq_state; +static volatile uint32_t sdmmc_block_size_log2; +static volatile bool sdmmc_write; +static volatile bool sdmmc_dma; +static volatile uint32_t sdmmc_error; +static volatile uint8_t *sdmmc_buf_cur; +static volatile uint8_t *sdmmc_buf_top; + +void sdio_init(uint32_t irq_pri) { + // configure IO pins + mp_hal_pin_config(pin_C8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); + mp_hal_pin_config(pin_C9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); + mp_hal_pin_config(pin_C10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); + mp_hal_pin_config(pin_C11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); + mp_hal_pin_config(pin_C12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 12); // CLK doesn't need pull-up + mp_hal_pin_config(pin_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, 12); + + __HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral + + SDMMC_TypeDef *SDIO = SDMMC1; + SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | 118; // 1-bit, 400kHz + mp_hal_delay_us(10); + SDIO->POWER = 3; // the card is clocked + mp_hal_delay_us(10); + SDIO->DCTRL = 1 << 10; // RWMOD is SDIO_CK + SDIO->CLKCR |= SDMMC_CLKCR_CLKEN; + mp_hal_delay_us(10); + + __HAL_RCC_DMA2_CLK_ENABLE(); // enable DMA2 peripheral + + NVIC_SetPriority(SDMMC1_IRQn, irq_pri); + + SDIO->MASK = 0; + HAL_NVIC_EnableIRQ(SDMMC1_IRQn); +} + +void sdio_deinit(void) { + RCC->APB2ENR &= ~RCC_APB2ENR_SDMMC1EN; // disable SDIO peripheral + RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA2EN; // disable DMA2 peripheral +} + +void sdio_enable_high_speed_4bit(void) { + SDMMC_TypeDef *SDIO = SDMMC1; + SDIO->POWER = 0; // power off + mp_hal_delay_us(10); + SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_WIDBUS_0 | SDMMC_CLKCR_BYPASS /*| SDMMC_CLKCR_PWRSAV*/; // 4-bit, 48MHz + mp_hal_delay_us(10); + SDIO->POWER = 3; // the card is clocked + mp_hal_delay_us(10); + SDIO->DCTRL = 1 << 11 | 1 << 10; // SDIOEN, RWMOD is SDIO_CK + SDIO->CLKCR |= SDMMC_CLKCR_CLKEN; + SDIO->MASK = DEFAULT_MASK; + mp_hal_delay_us(10); +} + +void SDMMC1_IRQHandler(void) { + if (SDMMC1->STA & SDMMC_STA_CMDREND) { + SDMMC1->ICR = SDMMC_ICR_CMDRENDC; + uint32_t r1 = SDMMC1->RESP1; + if (SDMMC1->RESPCMD == 53 && r1 & 0x800) { + printf("bad RESP1: %lu %lx\n", SDMMC1->RESPCMD, r1); + sdmmc_error = 0xffffffff; + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; + return; + } + if (sdmmc_buf_cur >= sdmmc_buf_top) { + // data transfer finished, so we are done + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; + return; + } + if (sdmmc_write) { + SDMMC1->DCTRL = (sdmmc_block_size_log2 << 4) | 1 | (1 << 11) | (!sdmmc_write << 1) | (sdmmc_dma << 3) | (0 << 10); + if (!sdmmc_dma) { + SDMMC1->MASK |= SDMMC_MASK_TXFIFOHEIE; + } + } + sdmmc_irq_state = SDMMC_IRQ_STATE_CMD_DONE; + } else if (SDMMC1->STA & SDMMC_STA_DATAEND) { + // data transfer complete + // note: it's possible to get DATAEND before CMDREND + SDMMC1->ICR = SDMMC_ICR_DATAENDC; + // check if there is some remaining data in RXFIFO + if (!sdmmc_dma) { + while (SDMMC1->STA & SDMMC_STA_RXDAVL) { + *(uint32_t*)sdmmc_buf_cur = SDMMC1->FIFO; + sdmmc_buf_cur += 4; + } + } + if (sdmmc_irq_state == SDMMC_IRQ_STATE_CMD_DONE) { + // command and data finished, so we are done + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; + } + } else if (SDMMC1->STA & SDMMC_STA_TXFIFOHE) { + if (!sdmmc_dma && sdmmc_write) { + // write up to 8 words to fifo + for (size_t i = 8; i && sdmmc_buf_cur < sdmmc_buf_top; --i) { + SDMMC1->FIFO = *(uint32_t*)sdmmc_buf_cur; + sdmmc_buf_cur += 4; + } + if (sdmmc_buf_cur >= sdmmc_buf_top) { + // finished, disable IRQ + SDMMC1->MASK &= ~SDMMC_MASK_TXFIFOHEIE; + } + } + } else if (SDMMC1->STA & SDMMC_STA_RXFIFOHF) { + if (!sdmmc_dma && !sdmmc_write) { + // read up to 8 words from fifo + for (size_t i = 8; i && sdmmc_buf_cur < sdmmc_buf_top; --i) { + *(uint32_t*)sdmmc_buf_cur = SDMMC1->FIFO; + sdmmc_buf_cur += 4; + } + } + } else if (SDMMC1->STA & SDMMC_STA_SDIOIT) { + SDMMC1->MASK &= ~SDMMC_MASK_SDIOITIE; + SDMMC1->ICR = SDMMC_ICR_SDIOITC; + + #if MICROPY_PY_NETWORK_CYW43 + extern void (*cyw43_poll)(void); + if (cyw43_poll) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); + } + #endif + } else if (SDMMC1->STA & 0x3f) { + // an error + sdmmc_error = SDMMC1->STA; + SDMMC1->ICR = SDMMC_STATIC_FLAGS; + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; + } +} + +int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) { + // Wait for any outstanding TX to complete + while (SDMMC1->STA & SDMMC_STA_TXACT) { + } + + DMA2_Stream3->CR = 0; // ensure DMA is reset + SDMMC1->ICR = SDMMC_STATIC_FLAGS; // clear interrupts + SDMMC1->ARG = arg; + SDMMC1->CMD = cmd | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; + + sdmmc_irq_state = SDMMC_IRQ_STATE_CMD_DATA_PENDING; + sdmmc_error = 0; + sdmmc_buf_cur = NULL; + sdmmc_buf_top = NULL; + SDMMC1->MASK = (SDMMC1->MASK & SDMMC_MASK_SDIOITIE) | SDMMC_MASK_CMDRENDIE | 0x3f; + + uint32_t start = mp_hal_ticks_ms(); + for (;;) { + __WFI(); + if (sdmmc_irq_state == SDMMC_IRQ_STATE_DONE) { + break; + } + if (mp_hal_ticks_ms() - start > 1000) { + SDMMC1->MASK = DEFAULT_MASK; + printf("sdio_transfer timeout STA=0x%08x\n", (uint)SDMMC1->STA); + return -MP_ETIMEDOUT; + } + } + + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + + if (sdmmc_error == SDMMC_STA_CCRCFAIL && cmd == 5) { + // Errata: CMD CRC error is incorrectly generated for CMD 5 + return 0; + } else if (sdmmc_error) { + return -(0x1000000 | sdmmc_error); + } + + uint32_t rcmd = SDMMC1->RESPCMD; + if (rcmd != cmd) { + printf("sdio_transfer: cmd=%lu rcmd=%lu\n", cmd, rcmd); + return -MP_EIO; + } + if (resp != NULL) { + *resp = SDMMC1->RESP1; + } + return 0; +} + +int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf) { + // Wait for any outstanding TX to complete + while (SDMMC1->STA & SDMMC_STA_TXACT) { + } + + // for SDIO_BYTE_MODE the SDIO chuck of data must be a single block of the length of buf + int block_size_log2 = 0; + if (block_size == 4) { + block_size_log2 = 2; + } else if (block_size == 8) { + block_size_log2 = 3; + } else if (block_size == 16) { + block_size_log2 = 4; + } else if (block_size == 32) { + block_size_log2 = 5; + } else if (block_size == 64) { + block_size_log2 = 6; + } else if (block_size == 128) { + block_size_log2 = 7; + } else if (block_size == 256) { + block_size_log2 = 8; + } else { + printf("sdio_transfer_cmd53: invalid block_size %lu", block_size); + return -MP_EINVAL; + } + + bool dma = (len > 16); + + SDMMC1->ICR = SDMMC_STATIC_FLAGS; // clear interrupts + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + + SDMMC1->DTIMER = 0x2000000; // about 700ms running at 48MHz + SDMMC1->DLEN = (len + block_size - 1) & ~(block_size - 1); + + DMA2_Stream3->CR = 0; + + if (dma) { + // prepare DMA so it's ready when the DPSM starts its transfer + + // enable DMA2 peripheral in case it was turned off by someone else + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; + + if (write) { + // make sure cache is flushed to RAM so the DMA can read the correct data + MP_HAL_CLEAN_DCACHE(buf, len); + } else { + // make sure cache is flushed and invalidated so when DMA updates the RAM + // from reading the peripheral the CPU then reads the new data + MP_HAL_CLEANINVALIDATE_DCACHE(buf, len); + } + + DMA2->LIFCR = 0x3f << 22; + DMA2_Stream3->FCR = 0x07; // ? + DMA2_Stream3->PAR = (uint32_t)&SDMMC1->FIFO; + if ((uint32_t)buf & 3) { + printf("sdio_transfer_cmd53: buf=%p is not aligned for DMA\n", buf); + return -MP_EINVAL; + } + DMA2_Stream3->M0AR = (uint32_t)buf; + DMA2_Stream3->NDTR = ((len + block_size - 1) & ~(block_size - 1)) / 4; + DMA2_Stream3->CR = 4 << 25 // channel 4 + | 1 << 23 // MBURST INCR4 + | 1 << 21 // PBURST INCR4 + | 3 << 16 // PL very high + | 2 << 13 // MSIZE word + | 2 << 11 // PSIZE word + | 1 << 10 // MINC enabled + | 0 << 9 // PINC disabled + | write << 6 // DIR mem-to-periph + | 1 << 5 // PFCTRL periph is flow controller + | 1 << 0 // EN + ; + } + + // for reading, need to initialise the DPSM before starting the CPSM + // so that the DPSM is ready to receive when the device sends data + // (and in case we get a long-running unrelated IRQ here on the host just + // after writing to CMD to initiate the command) + if (!write) { + SDMMC1->DCTRL = (block_size_log2 << 4) | 1 | (1 << 11) | (!write << 1) | (dma << 3); + } + + SDMMC1->ARG = arg; + SDMMC1->CMD = 53 | SDMMC_CMD_WAITRESP_0 | SDMMC_CMD_CPSMEN; + + sdmmc_irq_state = SDMMC_IRQ_STATE_CMD_DATA_PENDING; + sdmmc_block_size_log2 = block_size_log2; + sdmmc_write = write; + sdmmc_dma = dma; + sdmmc_error = 0; + sdmmc_buf_cur = (uint8_t*)buf; + sdmmc_buf_top = (uint8_t*)buf + len; + SDMMC1->MASK = (SDMMC1->MASK & SDMMC_MASK_SDIOITIE) | SDMMC_MASK_CMDRENDIE | SDMMC_MASK_DATAENDIE | SDMMC_MASK_RXFIFOHFIE | 0x3f; + + // wait to complete transfer + uint32_t start = mp_hal_ticks_ms(); + for (;;) { + __WFI(); + if (sdmmc_irq_state == SDMMC_IRQ_STATE_DONE) { + break; + } + if (mp_hal_ticks_ms() - start > 200) { + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + printf("sdio_transfer_cmd53: timeout wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR); + return -MP_ETIMEDOUT; + } + } + + SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + + if (sdmmc_error) { + printf("sdio_transfer_cmd53: error=%08lx wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", sdmmc_error, write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR); + return -(0x1000000 | sdmmc_error); + } + + if (!sdmmc_dma) { + if (sdmmc_buf_cur != sdmmc_buf_top) { + printf("sdio_transfer_cmd53: didn't transfer correct length: cur=%p top=%p\n", sdmmc_buf_cur, sdmmc_buf_top); + return -MP_EIO; + } + } + + return 0; +} + +#endif diff --git a/ports/stm32/sdio.h b/ports/stm32/sdio.h new file mode 100644 index 0000000000000..e7115e6f80c65 --- /dev/null +++ b/ports/stm32/sdio.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_SDIO_H +#define MICROPY_INCLUDED_STM32_SDIO_H + +#include +#include + +void sdio_init(uint32_t irq_pri); +void sdio_deinit(void); +void sdio_enable_high_speed_4bit(void); +int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp); +int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf); + +#endif // MICROPY_INCLUDED_STM32_SDIO_H From 8b7409c295ff243699ed6fa6bab1e18659b064cd Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:11:03 +1000 Subject: [PATCH 0149/1299] stm32: Integrate in the cyw43 driver and network.WLAN class. Enable it by setting MICROPY_PY_NETWORK_CYW43=1 at the Makefile level. --- ports/stm32/Makefile | 9 +++++++++ ports/stm32/extint.c | 10 ++++++++++ ports/stm32/main.c | 12 ++++++++++++ ports/stm32/modnetwork.c | 21 +++++++++++++++++++++ ports/stm32/pendsv.h | 3 +++ 5 files changed, 55 insertions(+) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 943acd4943fbc..6a44ff30b3e66 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -116,6 +116,7 @@ SRC_LIB = $(addprefix lib/,\ mp-readline/readline.c \ netutils/netutils.c \ netutils/trace.c \ + netutils/dhcpserver.c \ timeutils/timeutils.c \ utils/pyexec.c \ utils/interrupt_char.c \ @@ -351,6 +352,14 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ class/src/usbd_msc_data.c \ ) +ifeq ($(MICROPY_PY_NETWORK_CYW43),1) +CFLAGS_MOD += -DMICROPY_PY_NETWORK_CYW43=1 +SRC_C += sdio.c +EXTMOD_SRC_C += extmod/network_cyw43.c +DRIVERS_SRC_C += drivers/cyw43/cyw43_ctrl.c drivers/cyw43/cyw43_lwip.c +LIBS += $(TOP)/drivers/cyw43/libcyw43.a +endif + ifneq ($(MICROPY_PY_WIZNET5K),0) WIZNET5K_DIR=drivers/wiznet5k INC += -I$(TOP)/$(WIZNET5K_DIR) diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 1f147d42dc995..4a67d1824fb7f 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -31,6 +31,7 @@ #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" +#include "pendsv.h" #include "pin.h" #include "extint.h" #include "irq.h" @@ -613,6 +614,15 @@ void Handle_EXTI_Irq(uint32_t line) { __HAL_GPIO_EXTI_CLEAR_FLAG(1 << line); if (line < EXTI_NUM_VECTORS) { mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; + #if MICROPY_PY_NETWORK_CYW43 && defined(pyb_pin_WL_HOST_WAKE) + if (pyb_extint_callback_arg[line] == MP_OBJ_FROM_PTR(pyb_pin_WL_HOST_WAKE)) { + extern void (*cyw43_poll)(void); + if (cyw43_poll) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); + } + return; + } + #endif if (*cb != mp_const_none) { // If it's a soft IRQ handler then just schedule callback for later if (!pyb_extint_hard_irq[line]) { diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 02449a1b806a3..5bb425ddf349f 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -39,6 +39,7 @@ #if MICROPY_PY_LWIP #include "lwip/init.h" +#include "drivers/cyw43/cyw43.h" #endif #include "systick.h" @@ -481,6 +482,17 @@ void stm32_main(uint32_t reset_mode) { systick_enable_dispatch(SYSTICK_DISPATCH_LWIP, mod_network_lwip_poll_wrapper); #endif + #if MICROPY_PY_NETWORK_CYW43 + { + cyw43_init(&cyw43_state); + uint8_t buf[8]; + memcpy(&buf[0], "PYBD", 4); + mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, (char*)&buf[4]); + cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf); + cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t*)"pybd0123"); + } + #endif + #if defined(MICROPY_HW_UART_REPL) // Set up a UART REPL using a statically allocated object pyb_uart_repl_obj.base.type = &pyb_uart_type; diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index ea43f75573680..9d97ad4a0ebf9 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -44,6 +44,8 @@ #include "lwip/timeouts.h" #include "lwip/dns.h" #include "lwip/dhcp.h" +#include "extmod/network_cyw43.h" +#include "drivers/cyw43/cyw43.h" // Poll lwIP every 128ms #define LWIP_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0) @@ -70,6 +72,16 @@ void mod_network_lwip_poll_wrapper(uint32_t ticks_ms) { if (LWIP_TICK(ticks_ms)) { pendsv_schedule_dispatch(PENDSV_DISPATCH_LWIP, pyb_lwip_poll); } + + #if MICROPY_PY_NETWORK_CYW43 + if (cyw43_poll) { + if (cyw43_sleep != 0) { + if (--cyw43_sleep == 0) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); + } + } + } + #endif } #endif @@ -119,6 +131,9 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { #if defined(MICROPY_HW_ETH_MDC) { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&network_lan_type) }, #endif + #if MICROPY_PY_NETWORK_CYW43 + { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) }, + #endif #if MICROPY_PY_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) }, @@ -128,6 +143,12 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, + + // Constants + #if MICROPY_PY_NETWORK_CYW43 + { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(CYW43_ITF_STA)}, + { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(CYW43_ITF_AP)}, + #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); diff --git a/ports/stm32/pendsv.h b/ports/stm32/pendsv.h index 18ae1d63e9614..6cbfe8b2ecf1a 100644 --- a/ports/stm32/pendsv.h +++ b/ports/stm32/pendsv.h @@ -29,6 +29,9 @@ enum { #if MICROPY_PY_NETWORK && MICROPY_PY_LWIP PENDSV_DISPATCH_LWIP, + #if MICROPY_PY_NETWORK_CYW43 + PENDSV_DISPATCH_CYW43, + #endif #endif PENDSV_DISPATCH_MAX }; From 62fe47aa3a96056e03e4dffdf50a924f0cac1f06 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 1 Jun 2019 16:12:10 +1000 Subject: [PATCH 0150/1299] stm32/boards/PYBD_SFx: Enable CYW43 WLAN driver. --- ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 9 +++++++++ ports/stm32/boards/PYBD_SF2/mpconfigboard.mk | 4 ++++ ports/stm32/boards/PYBD_SF3/mpconfigboard.mk | 1 + ports/stm32/boards/PYBD_SF6/f767.ld | 3 +++ ports/stm32/boards/PYBD_SF6/mpconfigboard.mk | 1 + 5 files changed, 18 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index 8cafb0abe6f5b..49b46bce50d6e 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -7,6 +7,8 @@ FLASH_APP .text FLASH_APP .data + FLASH_EXT .big_const + RAM .data RAM .bss RAM .heap @@ -43,6 +45,13 @@ ENTRY(Reset_Handler) /* Define output sections */ SECTIONS { + .text_ext : + { + . = ALIGN(512); + *(.big_const*) + . = ALIGN(4); + } >FLASH_EXT + .isr_vector : { . = ALIGN(4); diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk index 87e397065618c..98103e1405637 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk @@ -5,6 +5,10 @@ MICROPY_FLOAT_IMPL = single AF_FILE = boards/stm32f722_af.csv LD_FILES = boards/PYBD_SF2/f722_qspi.ld TEXT0_ADDR = 0x08008000 +TEXT1_ADDR = 0x90000000 +TEXT0_SECTIONS = .isr_vector .text .data +TEXT1_SECTIONS = .text_ext # MicroPython settings MICROPY_PY_LWIP = 1 +MICROPY_PY_NETWORK_CYW43 = 1 diff --git a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk index 6104ed247591e..924a0f3d556d4 100644 --- a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk @@ -11,3 +11,4 @@ TEXT1_SECTIONS = .text_ext # MicroPython settings MICROPY_PY_LWIP = 1 +MICROPY_PY_NETWORK_CYW43 = 1 diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld index d910438a7ed9f..7f13eb45fe541 100644 --- a/ports/stm32/boards/PYBD_SF6/f767.ld +++ b/ports/stm32/boards/PYBD_SF6/f767.ld @@ -5,6 +5,7 @@ FLASH_APP .isr_vector FLASH_APP .text + FLASH_APP .big_const FLASH_APP .data RAM .data @@ -55,6 +56,8 @@ SECTIONS . = ALIGN(4); *(.text*) *(.rodata*) + . = ALIGN(512); + *(.big_const*) . = ALIGN(4); _etext = .; } >FLASH_APP diff --git a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk index 0288b9142c37e..50181232720c6 100644 --- a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk @@ -8,3 +8,4 @@ TEXT0_ADDR = 0x08008000 # MicroPython settings MICROPY_PY_LWIP = 1 +MICROPY_PY_NETWORK_CYW43 = 1 From ce8262a164d33d222de55677523593806404176e Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 3 Jun 2019 17:06:35 +1000 Subject: [PATCH 0151/1299] stm32/modnetwork: Replace generic netif NIC polling with specific code. It doesn't work to tie the polling of an underlying NIC driver (eg to check the NIC for pending Ethernet frames) with its associated lwIP netif. This is because most NICs are implemented with IRQs and don't need polling, because there can be multiple lwIP netif's per NIC driver, and because it restricts the use of the netif->state variable. Instead the NIC should have its own specific way of processing incoming Ethernet frame. This patch removes this generic NIC polling feature, and for the only driver that uses it (Wiznet5k) replaces it with an explicit call to the poll function (which could eventually be improved by using a proper external interrupt). --- ports/stm32/eth.c | 1 - ports/stm32/modnetwork.c | 14 +++++--------- ports/stm32/modnetwork.h | 7 ++----- ports/stm32/network_wiznet5k.c | 17 +++++++++-------- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/ports/stm32/eth.c b/ports/stm32/eth.c index 665495c17429c..6a1ef99afa3ba 100644 --- a/ports/stm32/eth.c +++ b/ports/stm32/eth.c @@ -107,7 +107,6 @@ typedef struct _eth_dma_t { } eth_dma_t; typedef struct _eth_t { - mod_network_nic_type_t base; uint32_t trace_flags; struct netif netif; struct dhcp dhcp_struct; diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index 9d97ad4a0ebf9..460f47257bac3 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -55,15 +55,11 @@ u32_t sys_now(void) { } STATIC void pyb_lwip_poll(void) { - // Poll all the NICs for incoming data - for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { - if (netif->flags & NETIF_FLAG_LINK_UP) { - mod_network_nic_type_t *nic = netif->state; - if (nic->poll_callback) { - nic->poll_callback(nic, netif); - } - } - } + #if MICROPY_PY_WIZNET5K + // Poll the NIC for incoming data + wiznet5k_poll(); + #endif + // Run the lwIP internal updates sys_check_timeouts(); } diff --git a/ports/stm32/modnetwork.h b/ports/stm32/modnetwork.h index 41a0017dab007..0b6d0c4a7fbcf 100644 --- a/ports/stm32/modnetwork.h +++ b/ports/stm32/modnetwork.h @@ -39,17 +39,14 @@ struct netif; -typedef struct _mod_network_nic_type_t { - mp_obj_base_t base; - void (*poll_callback)(void *data, struct netif *netif); -} mod_network_nic_type_t; - extern const mp_obj_type_t network_lan_type; extern const mp_obj_type_t mod_network_nic_type_wiznet5k; void mod_network_lwip_poll_wrapper(uint32_t ticks_ms); mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args); +void wiznet5k_poll(void); + #else struct _mod_network_socket_obj_t; diff --git a/ports/stm32/network_wiznet5k.c b/ports/stm32/network_wiznet5k.c index 3bbe639acc316..796b5551a797c 100644 --- a/ports/stm32/network_wiznet5k.c +++ b/ports/stm32/network_wiznet5k.c @@ -48,7 +48,7 @@ // Wiznet5k Ethernet driver in MACRAW mode typedef struct _wiznet5k_obj_t { - mod_network_nic_type_t base; + mp_obj_base_t base; mp_uint_t cris_state; const spi_t *spi; mp_hal_pin_obj_t cs; @@ -63,7 +63,6 @@ typedef struct _wiznet5k_obj_t { STATIC wiznet5k_obj_t wiznet5k_obj; STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self); -STATIC void wiznet5k_lwip_poll(void *self_in, struct netif *netif); STATIC void wiz_cris_enter(void) { wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION(); @@ -176,7 +175,7 @@ STATIC uint16_t wiznet5k_recv_ethernet(wiznet5k_obj_t *self) { uint16_t port; int ret = WIZCHIP_EXPORT(recvfrom)(0, self->eth_frame, 1514, ip, &port); if (ret <= 0) { - printf("wiznet5k_lwip_poll: fatal error len=%u ret=%d\n", len, ret); + printf("wiznet5k_poll: fatal error len=%u ret=%d\n", len, ret); netif_set_link_down(&self->netif); netif_set_down(&self->netif); return 0; @@ -237,8 +236,11 @@ STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self) { self->netif.flags &= ~NETIF_FLAG_UP; } -STATIC void wiznet5k_lwip_poll(void *self_in, struct netif *netif) { - wiznet5k_obj_t *self = self_in; +void wiznet5k_poll(void) { + wiznet5k_obj_t *self = &wiznet5k_obj; + if (!(self->netif.flags & NETIF_FLAG_LINK_UP)) { + return; + } uint16_t len; while ((len = wiznet5k_recv_ethernet(self)) > 0) { if (self->trace_flags & TRACE_ETH_RX) { @@ -267,7 +269,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size mp_hal_pin_obj_t rst = pin_find(args[2]); // Access the existing object, if it has been constructed with the same hardware interface - if (wiznet5k_obj.base.base.type == &mod_network_nic_type_wiznet5k) { + if (wiznet5k_obj.base.type == &mod_network_nic_type_wiznet5k) { if (!(wiznet5k_obj.spi == spi && wiznet5k_obj.cs == cs && wiznet5k_obj.rst == rst && wiznet5k_obj.netif.flags != 0)) { wiznet5k_deinit(); @@ -275,8 +277,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size } // Init the wiznet5k object - wiznet5k_obj.base.base.type = &mod_network_nic_type_wiznet5k; - wiznet5k_obj.base.poll_callback = wiznet5k_lwip_poll; + wiznet5k_obj.base.type = &mod_network_nic_type_wiznet5k; wiznet5k_obj.cris_state = 0; wiznet5k_obj.spi = spi; wiznet5k_obj.cs = cs; From faf3d3e9e93a71b3947bf563e4ffe13cbd053cb8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 4 Jun 2019 22:13:32 +1000 Subject: [PATCH 0152/1299] tools/mpy-tool.py: Fix linking qstrs in native code, and multiple files. Fixes errors in the tool when 1) linking qstrs in native ARM-M code; 2) freezing multiple files some of which use native code and some which don't. Fixes issue #4829. --- tools/mpy-tool.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index c8216bb603f2a..db6fe23833ca7 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -4,7 +4,7 @@ # # The MIT License (MIT) # -# Copyright (c) 2016 Damien P. George +# Copyright (c) 2016-2019 Damien P. George # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -479,18 +479,23 @@ def _asm_thumb_rewrite_mov(self, pc, val): def _link_qstr(self, pc, kind, qst): if kind == 0: + # Generic 16-bit link print(' %s & 0xff, %s >> 8,' % (qst, qst)) else: - if kind == 2: + # Architecture-specific link + is_obj = kind == 2 + if is_obj: qst = '((uintptr_t)MP_OBJ_NEW_QSTR(%s))' % qst if config.native_arch in (MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64): print(' %s & 0xff, %s >> 8, 0, 0,' % (qst, qst)) elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: if is_obj: - self._asm_thumb_rewrite_mov(i, qst) - self._asm_thumb_rewrite_mov(i + 4, '(%s >> 16)' % qst) + # qstr object, movw and movt + self._asm_thumb_rewrite_mov(pc, qst) + self._asm_thumb_rewrite_mov(pc + 4, '(%s >> 16)' % qst) else: - self._asm_thumb_rewrite_mov(i, qst) + # qstr number, movw instruction + self._asm_thumb_rewrite_mov(pc, qst) else: assert 0 @@ -663,7 +668,7 @@ def read_raw_code(f, qstr_win): # load qstr link table n_qstr_link = read_uint(f) for _ in range(n_qstr_link): - off = read_uint(f, qstr_win) + off = read_uint(f) qst = read_qstr(f, qstr_win) qstr_links.append((off >> 2, off & 3, qst)) @@ -714,7 +719,12 @@ def read_mpy(filename): qw_size = read_uint(f) config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE = (feature_byte & 1) != 0 config.MICROPY_PY_BUILTINS_STR_UNICODE = (feature_byte & 2) != 0 - config.native_arch = feature_byte >> 2 + mpy_native_arch = feature_byte >> 2 + if mpy_native_arch != MP_NATIVE_ARCH_NONE: + if config.native_arch == MP_NATIVE_ARCH_NONE: + config.native_arch = mpy_native_arch + elif config.native_arch != mpy_native_arch: + raise Exception('native architecture mismatch') config.mp_small_int_bits = header[3] qstr_win = QStrWindow(qw_size) return read_raw_code(f, qstr_win) @@ -838,6 +848,7 @@ def main(): 'mpz':config.MICROPY_LONGINT_IMPL_MPZ, }[args.mlongint_impl] config.MPZ_DIG_SIZE = args.mmpz_dig_size + config.native_arch = MP_NATIVE_ARCH_NONE # set config values for qstrs, and get the existing base set of qstrs if args.qstr_header: From 7cf26ca4bd84134b9fbddaf032370e91326edb64 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 4 Jun 2019 20:14:41 +0300 Subject: [PATCH 0153/1299] py/obj: Optimise small-int comparison to 0 in mp_obj_is_true. Instead of converting to a small-int at runtime this can be done at compile time, then we only have a simple comparison during runtime. This reduces code size on some ports (e.g -4 on qemu-arm, -52 on unix nanbox), and for others at least doesn't increase code size. --- py/obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/obj.c b/py/obj.c index 122f0ea624558..1797ee56bec5f 100644 --- a/py/obj.c +++ b/py/obj.c @@ -113,7 +113,7 @@ bool mp_obj_is_true(mp_obj_t arg) { } else if (arg == mp_const_none) { return 0; } else if (mp_obj_is_small_int(arg)) { - if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) { + if (arg == MP_OBJ_NEW_SMALL_INT(0)) { return 0; } else { return 1; From cd6b115815f8b618b27e2f49a7611de95983f6f4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 14:23:12 +1000 Subject: [PATCH 0154/1299] extmod: Factor out makefile rules from py.mk to new extmod.mk file. To logically separate extmod related rules out, and prevent py.mk from growing too large. --- extmod/extmod.mk | 121 +++++++++++++++++++++++++++++++++++++++++++++++ py/py.mk | 113 ++----------------------------------------- 2 files changed, 124 insertions(+), 110 deletions(-) create mode 100644 extmod/extmod.mk diff --git a/extmod/extmod.mk b/extmod/extmod.mk new file mode 100644 index 0000000000000..2143058f8fe49 --- /dev/null +++ b/extmod/extmod.mk @@ -0,0 +1,121 @@ +# This makefile fragment provides rules to build 3rd-party components for extmod modules + +# this sets the config file for FatFs +CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" + +################################################################################ +# ussl + +ifeq ($(MICROPY_PY_USSL),1) +CFLAGS_MOD += -DMICROPY_PY_USSL=1 +ifeq ($(MICROPY_SSL_AXTLS),1) +CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include +AXTLS_DIR = lib/axtls +$(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition $(AXTLS_DEFS_EXTRA) +SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ + ssl/asn1.c \ + ssl/loader.c \ + ssl/tls1.c \ + ssl/tls1_svr.c \ + ssl/tls1_clnt.c \ + ssl/x509.c \ + crypto/aes.c \ + crypto/bigint.c \ + crypto/crypto_misc.c \ + crypto/hmac.c \ + crypto/md5.c \ + crypto/rsa.c \ + crypto/sha1.c \ + ) +else ifeq ($(MICROPY_SSL_MBEDTLS),1) +# Can be overridden by ports which have "builtin" mbedTLS +MICROPY_SSL_MBEDTLS_INCLUDE ?= $(TOP)/lib/mbedtls/include +CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(MICROPY_SSL_MBEDTLS_INCLUDE) +LDFLAGS_MOD += -L$(TOP)/lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto +endif +endif + +################################################################################ +# lwip + +ifeq ($(MICROPY_PY_LWIP),1) +# A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include) +LWIP_DIR = lib/lwip/src +INC += -I$(TOP)/$(LWIP_DIR)/include +CFLAGS_MOD += -DMICROPY_PY_LWIP=1 +$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address +SRC_MOD += extmod/modlwip.c lib/netutils/netutils.c +SRC_MOD += $(addprefix $(LWIP_DIR)/,\ + core/def.c \ + core/dns.c \ + core/inet_chksum.c \ + core/init.c \ + core/ip.c \ + core/mem.c \ + core/memp.c \ + core/netif.c \ + core/pbuf.c \ + core/raw.c \ + core/stats.c \ + core/sys.c \ + core/tcp.c \ + core/tcp_in.c \ + core/tcp_out.c \ + core/timeouts.c \ + core/udp.c \ + core/ipv4/autoip.c \ + core/ipv4/dhcp.c \ + core/ipv4/etharp.c \ + core/ipv4/icmp.c \ + core/ipv4/igmp.c \ + core/ipv4/ip4_addr.c \ + core/ipv4/ip4.c \ + core/ipv4/ip4_frag.c \ + core/ipv6/dhcp6.c \ + core/ipv6/ethip6.c \ + core/ipv6/icmp6.c \ + core/ipv6/inet6.c \ + core/ipv6/ip6_addr.c \ + core/ipv6/ip6.c \ + core/ipv6/ip6_frag.c \ + core/ipv6/mld6.c \ + core/ipv6/nd6.c \ + netif/ethernet.c \ + ) +ifeq ($(MICROPY_PY_LWIP_SLIP),1) +CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1 +SRC_MOD += $(LWIP_DIR)/netif/slipif.c +endif +endif + +################################################################################ +# btree + +ifeq ($(MICROPY_PY_BTREE),1) +BTREE_DIR = lib/berkeley-db-1.xx +BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) +INC += -I$(TOP)/$(BTREE_DIR)/PORT/include +SRC_MOD += extmod/modbtree.c +SRC_MOD += $(addprefix $(BTREE_DIR)/,\ + btree/bt_close.c \ + btree/bt_conv.c \ + btree/bt_debug.c \ + btree/bt_delete.c \ + btree/bt_get.c \ + btree/bt_open.c \ + btree/bt_overflow.c \ + btree/bt_page.c \ + btree/bt_put.c \ + btree/bt_search.c \ + btree/bt_seq.c \ + btree/bt_split.c \ + btree/bt_utils.c \ + mpool/mpool.c \ + ) +CFLAGS_MOD += -DMICROPY_PY_BTREE=1 +# we need to suppress certain warnings to get berkeley-db to compile cleanly +# and we have separate BTREE_DEFS so the definitions don't interfere with other source code +$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) +$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS) +endif + diff --git a/py/py.mk b/py/py.mk index 3d8d849e2b57f..e649297e680c9 100644 --- a/py/py.mk +++ b/py/py.mk @@ -19,116 +19,6 @@ QSTR_GLOBAL_DEPENDENCIES += $(PY_SRC)/mpconfig.h mpconfigport.h # some code is performance bottleneck and compiled with other optimization options CSUPEROPT = -O3 -# this sets the config file for FatFs -CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" - -ifeq ($(MICROPY_PY_USSL),1) -CFLAGS_MOD += -DMICROPY_PY_USSL=1 -ifeq ($(MICROPY_SSL_AXTLS),1) -CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include -AXTLS_DIR = lib/axtls -$(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition $(AXTLS_DEFS_EXTRA) -SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ - ssl/asn1.c \ - ssl/loader.c \ - ssl/tls1.c \ - ssl/tls1_svr.c \ - ssl/tls1_clnt.c \ - ssl/x509.c \ - crypto/aes.c \ - crypto/bigint.c \ - crypto/crypto_misc.c \ - crypto/hmac.c \ - crypto/md5.c \ - crypto/rsa.c \ - crypto/sha1.c \ - ) -else ifeq ($(MICROPY_SSL_MBEDTLS),1) -# Can be overridden by ports which have "builtin" mbedTLS -MICROPY_SSL_MBEDTLS_INCLUDE ?= $(TOP)/lib/mbedtls/include -CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(MICROPY_SSL_MBEDTLS_INCLUDE) -LDFLAGS_MOD += -L$(TOP)/lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto -endif -endif - -ifeq ($(MICROPY_PY_LWIP),1) -# A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include) -LWIP_DIR = lib/lwip/src -INC += -I$(TOP)/$(LWIP_DIR)/include -CFLAGS_MOD += -DMICROPY_PY_LWIP=1 -$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address -SRC_MOD += extmod/modlwip.c lib/netutils/netutils.c -SRC_MOD += $(addprefix $(LWIP_DIR)/,\ - core/def.c \ - core/dns.c \ - core/inet_chksum.c \ - core/init.c \ - core/ip.c \ - core/mem.c \ - core/memp.c \ - core/netif.c \ - core/pbuf.c \ - core/raw.c \ - core/stats.c \ - core/sys.c \ - core/tcp.c \ - core/tcp_in.c \ - core/tcp_out.c \ - core/timeouts.c \ - core/udp.c \ - core/ipv4/autoip.c \ - core/ipv4/dhcp.c \ - core/ipv4/etharp.c \ - core/ipv4/icmp.c \ - core/ipv4/igmp.c \ - core/ipv4/ip4_addr.c \ - core/ipv4/ip4.c \ - core/ipv4/ip4_frag.c \ - core/ipv6/dhcp6.c \ - core/ipv6/ethip6.c \ - core/ipv6/icmp6.c \ - core/ipv6/inet6.c \ - core/ipv6/ip6_addr.c \ - core/ipv6/ip6.c \ - core/ipv6/ip6_frag.c \ - core/ipv6/mld6.c \ - core/ipv6/nd6.c \ - netif/ethernet.c \ - ) -ifeq ($(MICROPY_PY_LWIP_SLIP),1) -CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1 -SRC_MOD += $(LWIP_DIR)/netif/slipif.c -endif -endif - -ifeq ($(MICROPY_PY_BTREE),1) -BTREE_DIR = lib/berkeley-db-1.xx -BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) -INC += -I$(TOP)/$(BTREE_DIR)/PORT/include -SRC_MOD += extmod/modbtree.c -SRC_MOD += $(addprefix $(BTREE_DIR)/,\ -btree/bt_close.c \ -btree/bt_conv.c \ -btree/bt_debug.c \ -btree/bt_delete.c \ -btree/bt_get.c \ -btree/bt_open.c \ -btree/bt_overflow.c \ -btree/bt_page.c \ -btree/bt_put.c \ -btree/bt_search.c \ -btree/bt_seq.c \ -btree/bt_split.c \ -btree/bt_utils.c \ -mpool/mpool.c \ - ) -CFLAGS_MOD += -DMICROPY_PY_BTREE=1 -# we need to suppress certain warnings to get berkeley-db to compile cleanly -# and we have separate BTREE_DEFS so the definitions don't interfere with other source code -$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) -$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS) -endif - # External modules written in C. ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate @@ -365,3 +255,6 @@ $(PY_BUILD)/vm.o: CFLAGS += $(CSUPEROPT) # http://hg.python.org/cpython/file/b127046831e2/Python/ceval.c#l828 # http://www.emulators.com/docs/nx25_nostradamus.htm #-fno-crossjumping + +# Include rules for extmod related code +include $(TOP)/extmod/extmod.mk From 399417adbae831ba660cfcad3d75e2d5dab756ef Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 15:21:40 +1000 Subject: [PATCH 0155/1299] lib: Add new submodule for mbedtls, currently at v2.17.0. From upstream source: https://github.com/ARMmbed/mbedtls.git --- .gitmodules | 3 +++ lib/mbedtls | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/mbedtls diff --git a/.gitmodules b/.gitmodules index c986704caa416..216a3b909c31c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -18,3 +18,6 @@ [submodule "lib/nrfx"] path = lib/nrfx url = https://github.com/NordicSemiconductor/nrfx.git +[submodule "lib/mbedtls"] + path = lib/mbedtls + url = https://github.com/ARMmbed/mbedtls.git diff --git a/lib/mbedtls b/lib/mbedtls new file mode 160000 index 0000000000000..3f8d78411a26e --- /dev/null +++ b/lib/mbedtls @@ -0,0 +1 @@ +Subproject commit 3f8d78411a26e833db18d9fbde0e2f0baeda87f0 From 678ec182cd4d9b800ed22a98f0a1eb00b5e85aa6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 15:22:21 +1000 Subject: [PATCH 0156/1299] extmod/extmod.mk: Integrate mbedTLS so it is built from source. Setting MICROPY_PY_USSL and MICROPY_SSL_MBEDTLS at the Makefile-level will now build mbedTLS from source and include it in the build, with the ussl module using this TLS library. Extra settings like MBEDTLS_CONFIG_FILE may need to be provided by a given port. If a port wants to use its own mbedTLS library then it should not set MICROPY_SSL_MBEDTLS at the Makefile-level but rather set it at the C level, and provide the library as part of the build in its own way (see eg esp32 port). --- extmod/extmod.mk | 79 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 2143058f8fe49..909952cc28142 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -28,10 +28,81 @@ SRC_MOD += $(addprefix $(AXTLS_DIR)/,\ crypto/sha1.c \ ) else ifeq ($(MICROPY_SSL_MBEDTLS),1) -# Can be overridden by ports which have "builtin" mbedTLS -MICROPY_SSL_MBEDTLS_INCLUDE ?= $(TOP)/lib/mbedtls/include -CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(MICROPY_SSL_MBEDTLS_INCLUDE) -LDFLAGS_MOD += -L$(TOP)/lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto +MBEDTLS_DIR = lib/mbedtls +CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include +SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\ + aes.c \ + aesni.c \ + arc4.c \ + asn1parse.c \ + asn1write.c \ + base64.c \ + bignum.c \ + blowfish.c \ + camellia.c \ + ccm.c \ + certs.c \ + chacha20.c \ + chachapoly.c \ + cipher.c \ + cipher_wrap.c \ + cmac.c \ + ctr_drbg.c \ + debug.c \ + des.c \ + dhm.c \ + ecdh.c \ + ecdsa.c \ + ecjpake.c \ + ecp.c \ + ecp_curves.c \ + entropy.c \ + entropy_poll.c \ + error.c \ + gcm.c \ + havege.c \ + hmac_drbg.c \ + md2.c \ + md4.c \ + md5.c \ + md.c \ + md_wrap.c \ + oid.c \ + padlock.c \ + pem.c \ + pk.c \ + pkcs11.c \ + pkcs12.c \ + pkcs5.c \ + pkparse.c \ + pk_wrap.c \ + pkwrite.c \ + platform.c \ + platform_util.c \ + poly1305.c \ + ripemd160.c \ + rsa.c \ + rsa_internal.c \ + sha1.c \ + sha256.c \ + sha512.c \ + ssl_cache.c \ + ssl_ciphersuites.c \ + ssl_cli.c \ + ssl_cookie.c \ + ssl_srv.c \ + ssl_ticket.c \ + ssl_tls.c \ + timing.c \ + x509.c \ + x509_create.c \ + x509_crl.c \ + x509_crt.c \ + x509_csr.c \ + x509write_crt.c \ + x509write_csr.c \ + xtea.c \ + ) endif endif From 9d72f07b6de35c5901f93da7c95e00969caec6d6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 15:28:30 +1000 Subject: [PATCH 0157/1299] unix/mpconfigport.mk: Update comment about TLS implementations. As long as the submodule is checked out, mbedTLS is now fully integrated into the unix build if MICROPY_SSL_MBEDTLS=1. --- ports/unix/mpconfigport.mk | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index f0aa955c0c5b1..3a66d997b2f45 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -25,13 +25,11 @@ MICROPY_PY_FFI = 1 # ussl module requires one of the TLS libraries below MICROPY_PY_USSL = 1 -# axTLS has minimal size and fully integrated with MicroPython, but -# implements only a subset of modern TLS functionality, so may have -# problems with some servers. +# axTLS has minimal size but implements only a subset of modern TLS +# functionality, so may have problems with some servers. MICROPY_SSL_AXTLS = 1 # mbedTLS is more up to date and complete implementation, but also -# more bloated. Configuring and building of mbedTLS should be done -# outside of MicroPython, it can just link with mbedTLS library. +# more bloated. MICROPY_SSL_MBEDTLS = 0 # jni module requires JVM/JNI From ef7357d4abc5701865aa4d75d2e5488c3cc70160 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 15:33:15 +1000 Subject: [PATCH 0158/1299] extmod/modussl_mbedtls: Allow to build with object representation D. --- extmod/modussl_mbedtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 94863be57a9f7..6759f11fa5d69 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -334,7 +334,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; From fed4c23590e354394b275c073c46e3ad079877c3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 15:35:23 +1000 Subject: [PATCH 0159/1299] stm32: Integrate optional mbedTLS component for ussl module. To use it a board should define MICROPY_PY_USSL=1 and MICROPY_SSL_MBEDTLS=1 at the Makefile level. With the provided configuration it adds about 64k to the build. --- ports/stm32/Makefile | 5 ++ ports/stm32/mbedtls/mbedtls_config.h | 93 +++++++++++++++++++++++++++ ports/stm32/mbedtls/mbedtls_port.c | 96 ++++++++++++++++++++++++++++ ports/stm32/mpconfigport.h | 15 +++++ 4 files changed, 209 insertions(+) create mode 100644 ports/stm32/mbedtls/mbedtls_config.h create mode 100644 ports/stm32/mbedtls/mbedtls_port.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 6a44ff30b3e66..1216cd13bd169 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -396,6 +396,11 @@ SRC_MOD += $(addprefix $(CC3000_DIR)/src/,\ ) endif +ifeq ($(MICROPY_SSL_MBEDTLS),1) +CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' +SRC_MOD += mbedtls/mbedtls_port.c +endif + OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) diff --git a/ports/stm32/mbedtls/mbedtls_config.h b/ports/stm32/mbedtls/mbedtls_config.h new file mode 100644 index 0000000000000..4820140766f4d --- /dev/null +++ b/ports/stm32/mbedtls/mbedtls_config.h @@ -0,0 +1,93 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H +#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H + +// Set mbedtls configuration +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define MBEDTLS_DEPRECATED_REMOVED +#define MBEDTLS_ENTROPY_HARDWARE_ALT +#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_SHA256_SMALLER +#define MBEDTLS_SSL_PROTO_TLS1 +#define MBEDTLS_SSL_PROTO_TLS1_1 +#define MBEDTLS_SSL_PROTO_TLS1_2 +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +// Enable mbedtls modules +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +//#define MBEDTLS_ECP_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS5_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C + +// Memory allocation hooks +#include +#include +void *m_calloc_mbedtls(size_t nmemb, size_t size); +void m_free_mbedtls(void *ptr); +#define MBEDTLS_PLATFORM_STD_CALLOC m_calloc_mbedtls +#define MBEDTLS_PLATFORM_STD_FREE m_free_mbedtls +#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf + +#include "mbedtls/check_config.h" + +#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/stm32/mbedtls/mbedtls_port.c b/ports/stm32/mbedtls/mbedtls_port.c new file mode 100644 index 0000000000000..efb8d2c2a43ae --- /dev/null +++ b/ports/stm32/mbedtls/mbedtls_port.c @@ -0,0 +1,96 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/gc.h" +#include "rng.h" +#include "mbedtls_config.h" + +#define DEBUG (0) + +#if DEBUG +static size_t count_links(uint32_t *nb) { + void **p = MP_STATE_PORT(mbedtls_memory); + size_t n = 0; + *nb = 0; + while (p != NULL) { + ++n; + *nb += gc_nbytes(p); + p = (void**)p[1]; + } + return n; +} +#endif + +void *m_calloc_mbedtls(size_t nmemb, size_t size) { + void **ptr = m_malloc0(nmemb * size + 2 * sizeof(uintptr_t)); + #if DEBUG + uint32_t nb; + size_t n = count_links(&nb); + printf("mbed_alloc(%u, %u) -> (%u;%u) %p\n", nmemb, size, n, (uint)nb, ptr); + #endif + if (MP_STATE_PORT(mbedtls_memory) != NULL) { + MP_STATE_PORT(mbedtls_memory)[0] = ptr; + } + ptr[0] = NULL; + ptr[1] = MP_STATE_PORT(mbedtls_memory); + MP_STATE_PORT(mbedtls_memory) = ptr; + return &ptr[2]; +} + +void m_free_mbedtls(void *ptr_in) { + void **ptr = &((void**)ptr_in)[-2]; + #if DEBUG + uint32_t nb; + size_t n = count_links(&nb); + printf("mbed_free(%p, [%p, %p], nbytes=%u, links=%u;%u)\n", ptr, ptr[0], ptr[1], gc_nbytes(ptr), n, (uint)nb); + #endif + if (ptr[1] != NULL) { + ((void**)ptr[1])[0] = ptr[0]; + } + if (ptr[0] != NULL) { + ((void**)ptr[0])[1] = ptr[1]; + } else { + MP_STATE_PORT(mbedtls_memory) = ptr[1]; + } + m_free(ptr); +} + +int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) { + uint32_t val; + int n = 0; + *olen = len; + while (len--) { + if (!n) { + val = rng_get(); + n = 4; + } + *output++ = val; + val >>= 8; + --n; + } + return 0; +} diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 5a1687c07ba4d..d802300637f72 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -224,6 +224,12 @@ extern const struct _mp_obj_module_t mp_module_onewire; #define SOCKET_BUILTIN_MODULE_WEAK_LINKS #endif +#if MICROPY_PY_USSL +#define SSL_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_ssl), MP_ROM_PTR(&mp_module_ussl) }, +#else +#define SSL_BUILTIN_MODULE_WEAK_LINKS +#endif + #if MICROPY_PY_NETWORK #define NETWORK_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_network), MP_ROM_PTR(&mp_module_network) }, #else @@ -254,6 +260,7 @@ extern const struct _mp_obj_module_t mp_module_onewire; { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_module_uselect) }, \ SOCKET_BUILTIN_MODULE_WEAK_LINKS \ + SSL_BUILTIN_MODULE_WEAK_LINKS \ { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_ustruct) }, \ { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, \ @@ -267,6 +274,12 @@ extern const struct _mp_obj_module_t mp_module_onewire; #define MP_STATE_PORT MP_STATE_VM +#if MICROPY_SSL_MBEDTLS +#define MICROPY_PORT_ROOT_POINTER_MBEDTLS void **mbedtls_memory; +#else +#define MICROPY_PORT_ROOT_POINTER_MBEDTLS +#endif + #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ \ @@ -295,6 +308,8 @@ extern const struct _mp_obj_module_t mp_module_onewire; \ /* list of registered NICs */ \ mp_obj_list_t mod_network_nic_list; \ + \ + MICROPY_PORT_ROOT_POINTER_MBEDTLS // type definitions for the specific machine From fd839221fda6f53c794ecabe6d5eb05125307818 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 15:38:01 +1000 Subject: [PATCH 0160/1299] stm32/boards/PYBD_SFx: Enable ussl module using mbedTLS. --- ports/stm32/boards/PYBD_SF2/mpconfigboard.mk | 2 ++ ports/stm32/boards/PYBD_SF3/mpconfigboard.mk | 2 ++ ports/stm32/boards/PYBD_SF6/mpconfigboard.mk | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk index 98103e1405637..489d2f893a915 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk @@ -12,3 +12,5 @@ TEXT1_SECTIONS = .text_ext # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 diff --git a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk index 924a0f3d556d4..368adcf39a65a 100644 --- a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk @@ -12,3 +12,5 @@ TEXT1_SECTIONS = .text_ext # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 diff --git a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk index 50181232720c6..97c854ae77f74 100644 --- a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk @@ -9,3 +9,5 @@ TEXT0_ADDR = 0x08008000 # MicroPython settings MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 From 49388e339ecea9595c0e82244cc3d60a7cb5e333 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 16:13:34 +1000 Subject: [PATCH 0161/1299] extmod/extmod.mk: Include mdns app source in lwIP build. --- extmod/extmod.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 909952cc28142..05d0be3b1675c 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -117,6 +117,7 @@ CFLAGS_MOD += -DMICROPY_PY_LWIP=1 $(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address SRC_MOD += extmod/modlwip.c lib/netutils/netutils.c SRC_MOD += $(addprefix $(LWIP_DIR)/,\ + apps/mdns/mdns.c \ core/def.c \ core/dns.c \ core/inet_chksum.c \ From 9e4b3681fd82e9a520a93e09ae5ab4dd2e5c88ca Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 16:14:09 +1000 Subject: [PATCH 0162/1299] stm32: Support optional lwIP mDNS responder. --- ports/stm32/main.c | 4 ++++ ports/stm32/modnetwork.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 5bb425ddf349f..3852ff9b04eca 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -39,6 +39,7 @@ #if MICROPY_PY_LWIP #include "lwip/init.h" +#include "lwip/apps/mdns.h" #include "drivers/cyw43/cyw43.h" #endif @@ -479,6 +480,9 @@ void stm32_main(uint32_t reset_mode) { // because the system timeout list (next_timeout) is only ever reset by BSS clearing. // So for now we only init the lwIP stack once on power-up. lwip_init(); + #if LWIP_MDNS_RESPONDER + mdns_resp_init(); + #endif systick_enable_dispatch(SYSTICK_DISPATCH_LWIP, mod_network_lwip_poll_wrapper); #endif diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index 460f47257bac3..80e5a5a16257a 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -44,6 +44,7 @@ #include "lwip/timeouts.h" #include "lwip/dns.h" #include "lwip/dhcp.h" +#include "lwip/apps/mdns.h" #include "extmod/network_cyw43.h" #include "drivers/cyw43/cyw43.h" @@ -188,6 +189,10 @@ mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_o mp_hal_delay_ms(100); } + #if LWIP_MDNS_RESPONDER + mdns_resp_netif_settings_changed(netif); + #endif + return mp_const_none; } else { // Release and stop any existing DHCP @@ -202,6 +207,9 @@ mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_o ip_addr_t dns; netutils_parse_ipv4_addr(items[3], (uint8_t*)&dns, NETUTILS_BIG); dns_setserver(0, &dns); + #if LWIP_MDNS_RESPONDER + mdns_resp_netif_settings_changed(netif); + #endif return mp_const_none; } } From 62f004ba424920a01e60c7a9a064b8ec9cd69c12 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 5 Jun 2019 16:14:45 +1000 Subject: [PATCH 0163/1299] stm32/lwip_inc: Update to enable mDNS, TCP listen backlog, faster DHCP. --- ports/stm32/lwip_inc/lwipopts.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ports/stm32/lwip_inc/lwipopts.h b/ports/stm32/lwip_inc/lwipopts.h index 64ff104f7126b..8f54c83112bfc 100644 --- a/ports/stm32/lwip_inc/lwipopts.h +++ b/ports/stm32/lwip_inc/lwipopts.h @@ -3,6 +3,11 @@ #include +// This protection is not needed, instead we execute all lwIP code at PendSV priority +#define SYS_ARCH_DECL_PROTECT(lev) do { } while (0) +#define SYS_ARCH_PROTECT(lev) do { } while (0) +#define SYS_ARCH_UNPROTECT(lev) do { } while (0) + #define NO_SYS 1 #define SYS_LIGHTWEIGHT_PROT 1 #define MEM_ALIGNMENT 4 @@ -20,10 +25,17 @@ #define LWIP_IPV6 0 #define LWIP_DHCP 1 #define LWIP_DHCP_CHECK_LINK_UP 1 +#define DHCP_DOES_ARP_CHECK 0 // to speed DHCP up #define LWIP_DNS 1 +#define LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define LWIP_MDNS_RESPONDER 1 #define LWIP_IGMP 1 +#define LWIP_NUM_NETIF_CLIENT_DATA 1 // mDNS responder requires 1 +#define MEMP_NUM_UDP_PCB 5 // mDNS responder requires 1 + #define SO_REUSE 1 +#define TCP_LISTEN_BACKLOG 1 extern uint32_t rng_get(void); #define LWIP_RAND() rng_get() From 9d3031cc9d888321b122d7e92491ba045727ac32 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 11:36:39 +1000 Subject: [PATCH 0164/1299] tools/mpy-tool.py: Fix linking of qstr objects in native ARM Thumb code. Previously, when linking qstr objects in native code for ARM Thumb, the index into the machine code was being incremented by 4, not 8. It should be 8 to account for the size of the two machine instructions movw and movt. This patch makes sure the index into the machine code is incremented by the correct amount for all variations of qstr linking. See issue #4829. --- tools/mpy-tool.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index db6fe23833ca7..a97af7737f3c1 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -481,6 +481,7 @@ def _link_qstr(self, pc, kind, qst): if kind == 0: # Generic 16-bit link print(' %s & 0xff, %s >> 8,' % (qst, qst)) + return 2 else: # Architecture-specific link is_obj = kind == 2 @@ -488,14 +489,17 @@ def _link_qstr(self, pc, kind, qst): qst = '((uintptr_t)MP_OBJ_NEW_QSTR(%s))' % qst if config.native_arch in (MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64): print(' %s & 0xff, %s >> 8, 0, 0,' % (qst, qst)) + return 4 elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: if is_obj: # qstr object, movw and movt self._asm_thumb_rewrite_mov(pc, qst) self._asm_thumb_rewrite_mov(pc + 4, '(%s >> 16)' % qst) + return 8 else: # qstr number, movw instruction self._asm_thumb_rewrite_mov(pc, qst) + return 4 else: assert 0 @@ -523,8 +527,7 @@ def freeze(self, parent_name): # link qstr qi_off, qi_kind, qi_val = self.qstr_links[qi] qst = global_qstrs[qi_val].qstr_id - self._link_qstr(i, qi_kind, qst) - i += 4 + i += self._link_qstr(i, qi_kind, qst) qi += 1 else: # copy machine code (max 16 bytes) From 518aa571ab064ba8feb0b503f91fba0a62ad22b0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 14:38:56 +1000 Subject: [PATCH 0165/1299] stm32/usbd_msc: Rework USBD MSC code to support multiple logical units. SCSI can support multiple logical units over the one interface (in this case over USBD MSC) and here the MSC code is reworked to support this feature. At this point only one LU is used and the behaviour is mostly unchanged from before, except the INQUIRY result is different (it will report "Flash" for both flash and SD card). --- ports/stm32/Makefile | 2 +- ports/stm32/usb.c | 12 +- ports/stm32/usbd_msc_interface.c | 263 +++++++++++++++ ...sbd_msc_storage.h => usbd_msc_interface.h} | 11 +- ports/stm32/usbd_msc_storage.c | 306 ------------------ 5 files changed, 279 insertions(+), 315 deletions(-) create mode 100644 ports/stm32/usbd_msc_interface.c rename ports/stm32/{usbd_msc_storage.h => usbd_msc_interface.h} (82%) delete mode 100644 ports/stm32/usbd_msc_storage.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 1216cd13bd169..12edbcc7f7abe 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -222,7 +222,7 @@ SRC_C = \ usbd_desc.c \ usbd_cdc_interface.c \ usbd_hid_interface.c \ - usbd_msc_storage.c \ + usbd_msc_interface.c \ mphalport.c \ mpthreadport.c \ irq.c \ diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index ace090f804bb0..8a0591a49b0f2 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -31,7 +31,7 @@ #include "usbd_desc.h" #include "usbd_cdc_msc_hid.h" #include "usbd_cdc_interface.h" -#include "usbd_msc_storage.h" +#include "usbd_msc_interface.h" #include "usbd_hid_interface.h" #include "py/objstr.h" @@ -40,6 +40,8 @@ #include "py/mperrno.h" #include "py/mphal.h" #include "bufhelper.h" +#include "storage.h" +#include "sdcard.h" #include "usb.h" #if MICROPY_HW_ENABLE_USB @@ -143,16 +145,20 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInf return false; } + // Configure the MSC interface + const void *lu[1]; switch (pyb_usb_storage_medium) { #if MICROPY_HW_ENABLE_SDCARD case PYB_USB_STORAGE_MEDIUM_SDCARD: - USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops); + lu[0] = &pyb_sdcard_type; break; #endif default: - USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops); + lu[0] = &pyb_flash_type; break; } + usbd_msc_init_lu(1, lu); + USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops); // start the USB device USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0); diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c new file mode 100644 index 0000000000000..493dece1f929f --- /dev/null +++ b/ports/stm32/usbd_msc_interface.c @@ -0,0 +1,263 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "usbd_cdc_msc_hid.h" +#include "usbd_msc_interface.h" + +#include "extmod/vfs.h" +#include "storage.h" +#include "sdcard.h" + +#define USBD_MSC_MAX_LUN (2) + +// This flag is needed to support removal of the medium, so that the USB drive +// can be unmounted and won't be remounted automatically. +#define FLAGS_STARTED (0x01) + +#define FLAGS_READONLY (0x02) + +STATIC const void *usbd_msc_lu_data[USBD_MSC_MAX_LUN]; +STATIC uint8_t usbd_msc_lu_num; +STATIC uint16_t usbd_msc_lu_flags; + +static inline void lu_flag_set(uint8_t lun, uint8_t flag) { + usbd_msc_lu_flags |= flag << (lun * 2); +} + +static inline void lu_flag_clr(uint8_t lun, uint8_t flag) { + usbd_msc_lu_flags &= ~(flag << (lun * 2)); +} + +static inline bool lu_flag_is_set(uint8_t lun, uint8_t flag) { + return usbd_msc_lu_flags & (flag << (lun * 2)); +} + +STATIC const int8_t usbd_msc_inquiry_data[36] = { + 0x00, // peripheral qualifier; peripheral device type + 0x80, // 0x00 for a fixed drive, 0x80 for a removable drive + 0x02, // version + 0x02, // response data format + (STANDARD_INQUIRY_DATA_LEN - 5), // additional length + 0x00, // various flags + 0x00, // various flags + 0x00, // various flags + 'M', 'i', 'c', 'r', 'o', 'P', 'y', ' ', // Manufacturer : 8 bytes + 'p', 'y', 'b', 'o', 'a', 'r', 'd', ' ', // Product : 16 Bytes + 'F', 'l', 'a', 's', 'h', ' ', ' ', ' ', + '1', '.', '0' ,'0', // Version : 4 Bytes +}; + +// Set the logical units that will be exposed over MSC +void usbd_msc_init_lu(size_t lu_n, const void *lu_data) { + usbd_msc_lu_num = MIN(lu_n, USBD_MSC_MAX_LUN); + memcpy(usbd_msc_lu_data, lu_data, sizeof(void*) * usbd_msc_lu_num); + usbd_msc_lu_flags = 0; +} + +// Helper function to perform an ioctl on a logical unit +STATIC int lu_ioctl(uint8_t lun, int op, uint32_t *data) { + if (lun >= usbd_msc_lu_num) { + return -1; + } + const void *lu = usbd_msc_lu_data[lun]; + + if (lu == &pyb_flash_type) { + switch (op) { + case BP_IOCTL_INIT: + storage_init(); + *data = 0; + return 0; + case BP_IOCTL_SYNC: + storage_flush(); + return 0; + case BP_IOCTL_SEC_SIZE: + *data = storage_get_block_size(); + return 0; + case BP_IOCTL_SEC_COUNT: + *data = storage_get_block_count(); + return 0; + default: + return -1; + } + } else if (lu == &pyb_sdcard_type + #if MICROPY_HW_ENABLE_MMCARD + || lu == &pyb_mmcard_type + #endif + ) { + switch (op) { + case BP_IOCTL_INIT: + if (!sdcard_power_on()) { + return -1; + } + *data = 0; + return 0; + case BP_IOCTL_SYNC: + return 0; + case BP_IOCTL_SEC_SIZE: + *data = SDCARD_BLOCK_SIZE; + return 0; + case BP_IOCTL_SEC_COUNT: + *data = sdcard_get_capacity_in_bytes() / (uint64_t)SDCARD_BLOCK_SIZE; + return 0; + default: + return -1; + } + } else { + return -1; + } +} + +// Initialise all logical units (it's only ever called once, with lun_in=0) +STATIC int8_t usbd_msc_Init(uint8_t lun_in) { + if (lun_in != 0) { + return 0; + } + for (int lun = 0; lun < usbd_msc_lu_num; ++lun) { + uint32_t data = 0; + int res = lu_ioctl(lun, BP_IOCTL_INIT, &data); + if (res != 0) { + lu_flag_clr(lun, FLAGS_STARTED); + } else { + lu_flag_set(lun, FLAGS_STARTED); + if (data) { + lu_flag_set(lun, FLAGS_READONLY); + } + } + } + return 0; +} + +// Get storage capacity of a logical unit +STATIC int8_t usbd_msc_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { + uint32_t block_size_u32 = 0; + int res = lu_ioctl(lun, BP_IOCTL_SEC_SIZE, &block_size_u32); + if (res != 0) { + return -1; + } + *block_size = block_size_u32; + return lu_ioctl(lun, BP_IOCTL_SEC_COUNT, block_num); +} + +// Check if a logical unit is ready +STATIC int8_t usbd_msc_IsReady(uint8_t lun) { + if (lun >= usbd_msc_lu_num) { + return -1; + } + return lu_flag_is_set(lun, FLAGS_STARTED) ? 0 : -1; +} + +// Check if a logical unit is write protected +STATIC int8_t usbd_msc_IsWriteProtected(uint8_t lun) { + if (lun >= usbd_msc_lu_num) { + return -1; + } + return lu_flag_is_set(lun, FLAGS_READONLY) ? 1 : 0; +} + +// Start or stop a logical unit +STATIC int8_t usbd_msc_StartStopUnit(uint8_t lun, uint8_t started) { + if (lun >= usbd_msc_lu_num) { + return -1; + } + if (started) { + lu_flag_set(lun, FLAGS_STARTED); + } else { + lu_flag_clr(lun, FLAGS_STARTED); + } + return 0; +} + +// Prepare a logical unit for possible removal +STATIC int8_t usbd_msc_PreventAllowMediumRemoval(uint8_t lun, uint8_t param) { + uint32_t dummy; + // Sync the logical unit so the device can be unplugged/turned off + return lu_ioctl(lun, BP_IOCTL_SYNC, &dummy); +} + +// Read data from a logical unit +STATIC int8_t usbd_msc_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + if (lun >= usbd_msc_lu_num) { + return -1; + } + const void *lu = usbd_msc_lu_data[lun]; + + if (lu == &pyb_flash_type) { + storage_read_blocks(buf, blk_addr, blk_len); + return 0; + } else if (lu == &pyb_sdcard_type + #if MICROPY_HW_ENABLE_MMCARD + || lu == &pyb_mmcard_type + #endif + ) { + if (sdcard_read_blocks(buf, blk_addr, blk_len) == 0) { + return 0; + } + } + return -1; +} + +// Write data to a logical unit +STATIC int8_t usbd_msc_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + if (lun >= usbd_msc_lu_num) { + return -1; + } + const void *lu = usbd_msc_lu_data[lun]; + + if (lu == &pyb_flash_type) { + storage_write_blocks(buf, blk_addr, blk_len); + return 0; + } else if (lu == &pyb_sdcard_type + #if MICROPY_HW_ENABLE_MMCARD + || lu == &pyb_mmcard_type + #endif + ) { + if (sdcard_write_blocks(buf, blk_addr, blk_len) == 0) { + return 0; + } + } + return -1; +} + +// Get the number of attached logical units +STATIC int8_t usbd_msc_GetMaxLun(void) { + return usbd_msc_lu_num - 1; +} + +// Table of operations for the SCSI layer to call +const USBD_StorageTypeDef usbd_msc_fops = { + usbd_msc_Init, + usbd_msc_GetCapacity, + usbd_msc_IsReady, + usbd_msc_IsWriteProtected, + usbd_msc_StartStopUnit, + usbd_msc_PreventAllowMediumRemoval, + usbd_msc_Read, + usbd_msc_Write, + usbd_msc_GetMaxLun, + (int8_t *)usbd_msc_inquiry_data, +}; diff --git a/ports/stm32/usbd_msc_storage.h b/ports/stm32/usbd_msc_interface.h similarity index 82% rename from ports/stm32/usbd_msc_storage.h rename to ports/stm32/usbd_msc_interface.h index 669f7df5812a3..9d25a72a3a4ba 100644 --- a/ports/stm32/usbd_msc_storage.h +++ b/ports/stm32/usbd_msc_interface.h @@ -23,10 +23,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_STM32_USBD_MSC_STORAGE_H -#define MICROPY_INCLUDED_STM32_USBD_MSC_STORAGE_H +#ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H +#define MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H -extern const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops; -extern const USBD_StorageTypeDef USBD_SDCARD_STORAGE_fops; +extern const USBD_StorageTypeDef usbd_msc_fops; -#endif // MICROPY_INCLUDED_STM32_USBD_MSC_STORAGE_H +void usbd_msc_init_lu(size_t lu_n, const void *lu_data); + +#endif // MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H diff --git a/ports/stm32/usbd_msc_storage.c b/ports/stm32/usbd_msc_storage.c deleted file mode 100644 index 01d15f6e75c77..0000000000000 --- a/ports/stm32/usbd_msc_storage.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - */ - -/** - ****************************************************************************** - * @file usbd_storage_msd.c - * @author MCD application Team - * @version V1.1.0 - * @date 19-March-2012 - * @brief This file provides the disk operations functions. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2012 STMicroelectronics

- * - * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.st.com/software_license_agreement_liberty_v2 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Heavily modified by dpgeorge for MicroPython. - * - ****************************************************************************** - */ - -#include - -#include "usbd_cdc_msc_hid.h" -#include "usbd_msc_storage.h" - -#include "py/mpstate.h" -#include "storage.h" -#include "sdcard.h" - -// These are needed to support removal of the medium, so that the USB drive -// can be unmounted, and won't be remounted automatically. -static uint8_t flash_started = 0; - -#if MICROPY_HW_ENABLE_SDCARD -static uint8_t sdcard_started = 0; -#endif - -/******************************************************************************/ -// Callback functions for when the internal flash is the mass storage device - -static const int8_t FLASH_STORAGE_Inquirydata[] = { // 36 bytes - // LUN 0 - 0x00, - 0x80, // 0x00 for a fixed drive, 0x80 for a removable drive - 0x02, - 0x02, - (STANDARD_INQUIRY_DATA_LEN - 5), - 0x00, - 0x00, - 0x00, - 'u', 'P', 'y', ' ', ' ', ' ', ' ', ' ', // Manufacturer : 8 bytes - 'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', // Product : 16 Bytes - 'F', 'l', 'a', 's', 'h', ' ', ' ', ' ', - '1', '.', '0' ,'0', // Version : 4 Bytes -}; - -/** - * @brief Initialize the storage medium - * @param lun : logical unit number - * @retval Status - */ -int8_t FLASH_STORAGE_Init(uint8_t lun) { - storage_init(); - flash_started = 1; - return 0; -} - -/** - * @brief return medium capacity and block size - * @param lun : logical unit number - * @param block_num : number of physical block - * @param block_size : size of a physical block - * @retval Status - */ -int8_t FLASH_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { - *block_size = storage_get_block_size(); - *block_num = storage_get_block_count(); - return 0; -} - -/** - * @brief check whether the medium is ready - * @param lun : logical unit number - * @retval Status - */ -int8_t FLASH_STORAGE_IsReady(uint8_t lun) { - if (flash_started) { - return 0; - } - return -1; -} - -/** - * @brief check whether the medium is write-protected - * @param lun : logical unit number - * @retval Status - */ -int8_t FLASH_STORAGE_IsWriteProtected(uint8_t lun) { - return 0; -} - -// Remove the lun -int8_t FLASH_STORAGE_StartStopUnit(uint8_t lun, uint8_t started) { - flash_started = started; - return 0; -} - -int8_t FLASH_STORAGE_PreventAllowMediumRemoval(uint8_t lun, uint8_t param) { - // sync the flash so that the cache is cleared and the device can be unplugged/turned off - storage_flush(); - return 0; -} - -/** - * @brief Read data from the medium - * @param lun : logical unit number - * @param buf : Pointer to the buffer to save data - * @param blk_addr : address of 1st block to be read - * @param blk_len : nmber of blocks to be read - * @retval Status - */ -int8_t FLASH_STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { - storage_read_blocks(buf, blk_addr, blk_len); - return 0; -} - -/** - * @brief Write data to the medium - * @param lun : logical unit number - * @param buf : Pointer to the buffer to write from - * @param blk_addr : address of 1st block to be written - * @param blk_len : nmber of blocks to be read - * @retval Status - */ -int8_t FLASH_STORAGE_Write (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { - storage_write_blocks(buf, blk_addr, blk_len); - return 0; -} - -/** - * @brief Return number of supported logical unit - * @param None - * @retval number of logical unit - */ -int8_t FLASH_STORAGE_GetMaxLun(void) { - return 0; -} - -const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops = { - FLASH_STORAGE_Init, - FLASH_STORAGE_GetCapacity, - FLASH_STORAGE_IsReady, - FLASH_STORAGE_IsWriteProtected, - FLASH_STORAGE_StartStopUnit, - FLASH_STORAGE_PreventAllowMediumRemoval, - FLASH_STORAGE_Read, - FLASH_STORAGE_Write, - FLASH_STORAGE_GetMaxLun, - (int8_t *)FLASH_STORAGE_Inquirydata, -}; - -/******************************************************************************/ -// Callback functions for when the SD card is the mass storage device - -#if MICROPY_HW_ENABLE_SDCARD - -static const int8_t SDCARD_STORAGE_Inquirydata[] = { // 36 bytes - // LUN 0 - 0x00, - 0x80, // 0x00 for a fixed drive, 0x80 for a removable drive - 0x02, - 0x02, - (STANDARD_INQUIRY_DATA_LEN - 5), - 0x00, - 0x00, - 0x00, - 'u', 'P', 'y', ' ', ' ', ' ', ' ', ' ', // Manufacturer : 8 bytes - 'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', // Product : 16 Bytes - 'S', 'D', ' ', 'c', 'a', 'r', 'd', ' ', - '1', '.', '0' ,'0', // Version : 4 Bytes -}; - -/** - * @brief Initialize the storage medium - * @param lun : logical unit number - * @retval Status - */ -int8_t SDCARD_STORAGE_Init(uint8_t lun) { - if (!sdcard_power_on()) { - return -1; - } - sdcard_started = 1; - return 0; - -} - -/** - * @brief return medium capacity and block size - * @param lun : logical unit number - * @param block_num : number of physical block - * @param block_size : size of a physical block - * @retval Status - */ -int8_t SDCARD_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { - *block_size = SDCARD_BLOCK_SIZE; - *block_num = sdcard_get_capacity_in_bytes() / SDCARD_BLOCK_SIZE; - return 0; -} - -/** - * @brief check whether the medium is ready - * @param lun : logical unit number - * @retval Status - */ -int8_t SDCARD_STORAGE_IsReady(uint8_t lun) { - if (sdcard_started) { - return 0; - } - return -1; -} - -/** - * @brief check whether the medium is write-protected - * @param lun : logical unit number - * @retval Status - */ -int8_t SDCARD_STORAGE_IsWriteProtected(uint8_t lun) { - return 0; -} - -// Remove the lun -int8_t SDCARD_STORAGE_StartStopUnit(uint8_t lun, uint8_t started) { - sdcard_started = started; - return 0; -} - -int8_t SDCARD_STORAGE_PreventAllowMediumRemoval(uint8_t lun, uint8_t param) { - return 0; -} - -/** - * @brief Read data from the medium - * @param lun : logical unit number - * @param buf : Pointer to the buffer to save data - * @param blk_addr : address of 1st block to be read - * @param blk_len : nmber of blocks to be read - * @retval Status - */ -int8_t SDCARD_STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { - if (sdcard_read_blocks(buf, blk_addr, blk_len) != 0) { - return -1; - } - return 0; -} - -/** - * @brief Write data to the medium - * @param lun : logical unit number - * @param buf : Pointer to the buffer to write from - * @param blk_addr : address of 1st block to be written - * @param blk_len : nmber of blocks to be read - * @retval Status - */ -int8_t SDCARD_STORAGE_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { - if (sdcard_write_blocks(buf, blk_addr, blk_len) != 0) { - return -1; - } - return 0; -} - -/** - * @brief Return number of supported logical unit - * @param None - * @retval number of logical unit - */ -int8_t SDCARD_STORAGE_GetMaxLun(void) { - return 0; -} - -const USBD_StorageTypeDef USBD_SDCARD_STORAGE_fops = { - SDCARD_STORAGE_Init, - SDCARD_STORAGE_GetCapacity, - SDCARD_STORAGE_IsReady, - SDCARD_STORAGE_IsWriteProtected, - SDCARD_STORAGE_StartStopUnit, - SDCARD_STORAGE_PreventAllowMediumRemoval, - SDCARD_STORAGE_Read, - SDCARD_STORAGE_Write, - SDCARD_STORAGE_GetMaxLun, - (int8_t *)SDCARD_STORAGE_Inquirydata, -}; - -#endif // MICROPY_HW_ENABLE_SDCARD From 829aa58c5ca5dc9681b642c27c9a6906957ca643 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 15:23:22 +1000 Subject: [PATCH 0166/1299] stm32/usbd_msc: Provide custom irquiry processing by MSC interface. So the MSC interface can customise the inquiry response based on the attached logical units. --- ports/stm32/usbd_msc_interface.c | 59 ++++++++++++++++++- .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 2 +- ports/stm32/usbdev/class/src/usbd_msc_scsi.c | 28 ++------- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c index 493dece1f929f..6a81d14f63bbf 100644 --- a/ports/stm32/usbd_msc_interface.c +++ b/ports/stm32/usbd_msc_interface.c @@ -57,6 +57,21 @@ static inline bool lu_flag_is_set(uint8_t lun, uint8_t flag) { return usbd_msc_lu_flags & (flag << (lun * 2)); } +STATIC const uint8_t usbd_msc_vpd00[6] = { + 0x00, // peripheral qualifier; peripheral device type + 0x00, // page code + 0x00, // reserved + 2, // page length (additional bytes beyond this entry) + 0x00, // page 0x00 supported + 0x83, // page 0x83 supported +}; + +STATIC const uint8_t usbd_msc_vpd83[4] = { + 0x00, // peripheral qualifier; peripheral device type + 0x83, // page code + 0x00, 0x00, // page length (additional bytes beyond this entry) +}; + STATIC const int8_t usbd_msc_inquiry_data[36] = { 0x00, // peripheral qualifier; peripheral device type 0x80, // 0x00 for a fixed drive, 0x80 for a removable drive @@ -152,6 +167,48 @@ STATIC int8_t usbd_msc_Init(uint8_t lun_in) { return 0; } +// Process SCSI INQUIRY command for the logical unit +STATIC int usbd_msc_Inquiry(uint8_t lun, const uint8_t *params, uint8_t *data_out) { + if (params[1] & 1) { + // EVPD set - return vital product data parameters + uint8_t page_code = params[2]; + switch (page_code) { + case 0x00: // Supported VPD pages + memcpy(data_out, usbd_msc_vpd00, sizeof(usbd_msc_vpd00)); + return sizeof(usbd_msc_vpd00); + case 0x83: // Device identification + memcpy(data_out, usbd_msc_vpd83, sizeof(usbd_msc_vpd83)); + return sizeof(usbd_msc_vpd83); + default: // Unsupported + return -1; + } + } + + // A standard inquiry + + if (lun >= usbd_msc_lu_num) { + return -1; + } + const void *lu = usbd_msc_lu_data[lun]; + + uint8_t alloc_len = params[3] << 8 | params[4]; + int len = MIN(sizeof(usbd_msc_inquiry_data), alloc_len); + memcpy(data_out, usbd_msc_inquiry_data, len); + + if (len == sizeof(usbd_msc_inquiry_data)) { + if (lu == &pyb_sdcard_type) { + memcpy(data_out + 24, "SDCard", sizeof("SDCard") - 1); + } + #if MICROPY_HW_ENABLE_MMCARD + else if (lu == &pyb_mmcard_type) { + memcpy(data_out + 24, "MMCard", sizeof("MMCard") - 1); + } + #endif + } + + return len; +} + // Get storage capacity of a logical unit STATIC int8_t usbd_msc_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { uint32_t block_size_u32 = 0; @@ -251,6 +308,7 @@ STATIC int8_t usbd_msc_GetMaxLun(void) { // Table of operations for the SCSI layer to call const USBD_StorageTypeDef usbd_msc_fops = { usbd_msc_Init, + usbd_msc_Inquiry, usbd_msc_GetCapacity, usbd_msc_IsReady, usbd_msc_IsWriteProtected, @@ -259,5 +317,4 @@ const USBD_StorageTypeDef usbd_msc_fops = { usbd_msc_Read, usbd_msc_Write, usbd_msc_GetMaxLun, - (int8_t *)usbd_msc_inquiry_data, }; diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index d46f763d1dc41..eaa39f1878ea0 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -61,6 +61,7 @@ typedef struct { typedef struct _USBD_STORAGE { int8_t (* Init) (uint8_t lun); + int (* Inquiry) (uint8_t lun, const uint8_t *params, uint8_t *data_out); int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size); int8_t (* IsReady) (uint8_t lun); int8_t (* IsWriteProtected) (uint8_t lun); @@ -69,7 +70,6 @@ typedef struct _USBD_STORAGE { int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t (* GetMaxLun)(void); - int8_t *pInquiry; } USBD_StorageTypeDef; typedef struct { diff --git a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c index 9da90337716da..8651b3ca871ad 100644 --- a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c +++ b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c @@ -225,33 +225,15 @@ static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t */ static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { - uint8_t* pPage; - uint16_t len; USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; - if (params[1] & 0x01)/*Evpd is set*/ + int res = hmsc->bdev_ops->Inquiry(lun, params, hmsc->bot_data); + if (res < 0) { - pPage = (uint8_t *)MSC_Page00_Inquiry_Data; - len = LENGTH_INQUIRY_PAGE00; - } - else - { - - pPage = (uint8_t *)&hmsc->bdev_ops->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN]; - len = pPage[4] + 5; - - if (params[4] <= len) - { - len = params[4]; - } - } - hmsc->bot_data_length = len; - - while (len) - { - len--; - hmsc->bot_data[len] = pPage[len]; + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; } + hmsc->bot_data_length = res; return 0; } From 38bcc99a586d7d6e5f51fcb330a12c4c42007162 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 15:35:15 +1000 Subject: [PATCH 0167/1299] stm32/usbd_msc: Provide Mode Sense response data in MSC interface. Eventually these responses could be filled in by a function to make their contents dynamic, depending on the attached logical units. But for now they are fixed, and this patch fixes the MODE SENSE(6) responses so it is the correct length with the correct header. --- ports/stm32/Makefile | 1 - ports/stm32/usbd_msc_interface.c | 18 +++ .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 3 + ports/stm32/usbdev/class/inc/usbd_msc_data.h | 104 -------------- ports/stm32/usbdev/class/src/usbd_msc_data.c | 134 ------------------ ports/stm32/usbdev/class/src/usbd_msc_scsi.c | 9 +- 6 files changed, 25 insertions(+), 244 deletions(-) delete mode 100644 ports/stm32/usbdev/class/inc/usbd_msc_data.h delete mode 100644 ports/stm32/usbdev/class/src/usbd_msc_data.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 12edbcc7f7abe..4c9a2342ca8c2 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -349,7 +349,6 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ class/src/usbd_cdc_msc_hid.c \ class/src/usbd_msc_bot.c \ class/src/usbd_msc_scsi.c \ - class/src/usbd_msc_data.c \ ) ifeq ($(MICROPY_PY_NETWORK_CYW43),1) diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c index 6a81d14f63bbf..0148fc7c6c2d0 100644 --- a/ports/stm32/usbd_msc_interface.c +++ b/ports/stm32/usbd_msc_interface.c @@ -57,6 +57,24 @@ static inline bool lu_flag_is_set(uint8_t lun, uint8_t flag) { return usbd_msc_lu_flags & (flag << (lun * 2)); } +// Sent in response to MODE SENSE(6) command +const uint8_t USBD_MSC_Mode_Sense6_Data[4] = { + 0x03, // mode data length + 0x00, // medium type + 0x00, // bit 7: write protect + 0x00, // block descriptor length +}; + +// Sent in response to MODE SENSE(10) command +const uint8_t USBD_MSC_Mode_Sense10_Data[8] = { + 0x00, 0x06, // mode data length + 0x00, // medium type + 0x00, // bit 7: write protect + 0x00, + 0x00, + 0x00, 0x00, // block descriptor length +}; + STATIC const uint8_t usbd_msc_vpd00[6] = { 0x00, // peripheral qualifier; peripheral device type 0x00, // page code diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index eaa39f1878ea0..c41908d25b13f 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -131,6 +131,9 @@ typedef struct _usbd_cdc_msc_hid_state_t { usbd_hid_state_t *hid; } usbd_cdc_msc_hid_state_t; +extern const uint8_t USBD_MSC_Mode_Sense6_Data[4]; +extern const uint8_t USBD_MSC_Mode_Sense10_Data[8]; + #define USBD_HID_MOUSE_MAX_PACKET (4) #define USBD_HID_MOUSE_REPORT_DESC_SIZE (74) diff --git a/ports/stm32/usbdev/class/inc/usbd_msc_data.h b/ports/stm32/usbdev/class/inc/usbd_msc_data.h deleted file mode 100644 index afd39e4f0940e..0000000000000 --- a/ports/stm32/usbdev/class/inc/usbd_msc_data.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - ****************************************************************************** - * @file usbd_msc_data.h - * @author MCD Application Team - * @version V2.0.0 - * @date 18-February-2014 - * @brief header for the usbd_msc_data.c file - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2014 STMicroelectronics

- * - * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.st.com/software_license_agreement_liberty_v2 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ - -#ifndef _USBD_MSC_DATA_H_ -#define _USBD_MSC_DATA_H_ - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_conf.h" - -/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY - * @{ - */ - -/** @defgroup USB_INFO - * @brief general defines for the usb device library file - * @{ - */ - -/** @defgroup USB_INFO_Exported_Defines - * @{ - */ -#define MODE_SENSE6_LEN 8 -#define MODE_SENSE10_LEN 8 -#define LENGTH_INQUIRY_PAGE00 7 -#define LENGTH_FORMAT_CAPACITIES 20 - -/** - * @} - */ - - -/** @defgroup USBD_INFO_Exported_TypesDefinitions - * @{ - */ -/** - * @} - */ - - - -/** @defgroup USBD_INFO_Exported_Macros - * @{ - */ - -/** - * @} - */ - -/** @defgroup USBD_INFO_Exported_Variables - * @{ - */ -extern const uint8_t MSC_Page00_Inquiry_Data[]; -extern const uint8_t MSC_Mode_Sense6_data[]; -extern const uint8_t MSC_Mode_Sense10_data[] ; - -/** - * @} - */ - -/** @defgroup USBD_INFO_Exported_FunctionsPrototype - * @{ - */ - -/** - * @} - */ - -#endif /* _USBD_MSC_DATA_H_ */ - -/** - * @} - */ - -/** -* @} -*/ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbdev/class/src/usbd_msc_data.c b/ports/stm32/usbdev/class/src/usbd_msc_data.c deleted file mode 100644 index 96740a3a4fba2..0000000000000 --- a/ports/stm32/usbdev/class/src/usbd_msc_data.c +++ /dev/null @@ -1,134 +0,0 @@ -/** - ****************************************************************************** - * @file usbd_msc_data.c - * @author MCD Application Team - * @version V2.0.0 - * @date 18-February-2014 - * @brief This file provides all the vital inquiry pages and sense data. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2014 STMicroelectronics

- * - * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.st.com/software_license_agreement_liberty_v2 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_msc_data.h" - - -/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY - * @{ - */ - - -/** @defgroup MSC_DATA - * @brief Mass storage info/data module - * @{ - */ - -/** @defgroup MSC_DATA_Private_TypesDefinitions - * @{ - */ -/** - * @} - */ - - -/** @defgroup MSC_DATA_Private_Defines - * @{ - */ -/** - * @} - */ - - -/** @defgroup MSC_DATA_Private_Macros - * @{ - */ -/** - * @} - */ - - -/** @defgroup MSC_DATA_Private_Variables - * @{ - */ - - -/* USB Mass storage Page 0 Inquiry Data */ -const uint8_t MSC_Page00_Inquiry_Data[] = {//7 - 0x00, - 0x00, - 0x00, - (LENGTH_INQUIRY_PAGE00 - 4), - 0x00, - 0x80, - 0x83 -}; -/* USB Mass storage sense 6 Data */ -const uint8_t MSC_Mode_Sense6_data[] = { - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00 -}; -/* USB Mass storage sense 10 Data */ -const uint8_t MSC_Mode_Sense10_data[] = { - 0x00, - 0x06, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00 -}; -/** - * @} - */ - - -/** @defgroup MSC_DATA_Private_FunctionPrototypes - * @{ - */ -/** - * @} - */ - - -/** @defgroup MSC_DATA_Private_Functions - * @{ - */ - -/** - * @} - */ - - -/** - * @} - */ - - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c index 8651b3ca871ad..26556bb48e8af 100644 --- a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c +++ b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c @@ -28,7 +28,6 @@ /* Includes ------------------------------------------------------------------*/ #include "usbd_msc_bot.h" #include "usbd_msc_scsi.h" -#include "usbd_msc_data.h" #include "usbd_cdc_msc_hid.h" @@ -328,13 +327,13 @@ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, ui static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; - uint16_t len = 8 ; + uint16_t len = sizeof(USBD_MSC_Mode_Sense6_Data); hmsc->bot_data_length = len; while (len) { len--; - hmsc->bot_data[len] = MSC_Mode_Sense6_data[len]; + hmsc->bot_data[len] = USBD_MSC_Mode_Sense6_Data[len]; } return 0; } @@ -348,7 +347,7 @@ static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t * */ static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { - uint16_t len = 8; + uint16_t len = sizeof(USBD_MSC_Mode_Sense10_Data); USBD_MSC_BOT_HandleTypeDef *hmsc = &((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->MSC_BOT_ClassData; hmsc->bot_data_length = len; @@ -356,7 +355,7 @@ static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t while (len) { len--; - hmsc->bot_data[len] = MSC_Mode_Sense10_data[len]; + hmsc->bot_data[len] = USBD_MSC_Mode_Sense10_Data[len]; } return 0; } From 9e68eec8eac1188eab0bc059560b877928783978 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 15:50:21 +1000 Subject: [PATCH 0168/1299] stm32/usb: Use ARG_xxx enums to access kw args in pyb_usb_mode. --- ports/stm32/usb.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8a0591a49b0f2..1582654115f82 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -226,6 +226,7 @@ usbd_cdc_itf_t *usb_vcp_get(int idx) { */ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_vid, ARG_pid, ARG_hid, ARG_high_speed }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_vid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = USBD_VID} }, @@ -269,14 +270,14 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pyb_usb_flags |= PYB_USB_FLAG_USB_MODE_CALLED; // check if user wants to disable the USB - if (args[0].u_obj == mp_const_none) { + if (args[ARG_mode].u_obj == mp_const_none) { // disable usb pyb_usb_dev_deinit(); return mp_const_none; } // get mode string - const char *mode_str = mp_obj_str_get_str(args[0].u_obj); + const char *mode_str = mp_obj_str_get_str(args[ARG_mode].u_obj); #if defined(USE_HOST_MODE) @@ -295,50 +296,50 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // get the VID, PID and USB mode // note: PID=-1 means select PID based on mode // note: we support CDC as a synonym for VCP for backward compatibility - uint16_t vid = args[1].u_int; - uint16_t pid = args[2].u_int; + uint16_t vid = args[ARG_vid].u_int; + uint16_t pid = args[ARG_pid].u_int; uint8_t mode; if (strcmp(mode_str, "CDC+MSC") == 0 || strcmp(mode_str, "VCP+MSC") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_CDC_MSC; } mode = USBD_MODE_CDC_MSC; #if MICROPY_HW_USB_CDC_NUM >= 2 } else if (strcmp(mode_str, "VCP+VCP") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_CDC2; } mode = USBD_MODE_CDC2; } else if (strcmp(mode_str, "VCP+VCP+MSC") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_CDC2_MSC; } mode = USBD_MODE_CDC2_MSC; #endif #if MICROPY_HW_USB_CDC_NUM >= 3 } else if (strcmp(mode_str, "3xVCP") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_CDC3; } mode = USBD_MODE_CDC3; } else if (strcmp(mode_str, "3xVCP+MSC") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_CDC3_MSC; } mode = USBD_MODE_CDC3_MSC; #endif } else if (strcmp(mode_str, "CDC+HID") == 0 || strcmp(mode_str, "VCP+HID") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_CDC_HID; } mode = USBD_MODE_CDC_HID; } else if (strcmp(mode_str, "CDC") == 0 || strcmp(mode_str, "VCP") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_CDC; } mode = USBD_MODE_CDC; } else if (strcmp(mode_str, "MSC") == 0) { - if (args[2].u_int == -1) { + if (pid == -1) { pid = USBD_PID_MSC; } mode = USBD_MODE_MSC; @@ -350,7 +351,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * USBD_HID_ModeInfoTypeDef hid_info; if (mode & USBD_MODE_IFACE_HID) { mp_obj_t *items; - mp_obj_get_array_fixed_n(args[3].u_obj, 5, &items); + mp_obj_get_array_fixed_n(args[ARG_hid].u_obj, 5, &items); hid_info.subclass = mp_obj_get_int(items[0]); hid_info.protocol = mp_obj_get_int(items[1]); hid_info.max_packet_len = mp_obj_get_int(items[2]); @@ -365,7 +366,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * } #if USBD_SUPPORT_HS_MODE - if (args[4].u_bool) { + if (args[ARG_high_speed].u_bool) { mode |= USBD_MODE_HIGH_SPEED; } #endif From 53200247b779358ffa03e1b7a8d1e9964befc234 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 16:10:52 +1000 Subject: [PATCH 0169/1299] stm32/usb: Add "msc" kw-arg to pyb.usb_mode to select MSC logical units. With this the user can select multiple logical units to expose over USB MSC at once, eg: pyb.usb_mode('VCP+MSC', msc=(pyb.Flash(), pyb.SDCard())). The default behaviour is the original behaviour of just one unit at a time. --- ports/stm32/main.c | 2 +- ports/stm32/usb.c | 57 ++++++++++++++++++++++++-------- ports/stm32/usb.h | 2 +- ports/stm32/usbd_msc_interface.c | 2 -- ports/stm32/usbd_msc_interface.h | 2 ++ 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 3852ff9b04eca..44e29921b1c84 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -645,7 +645,7 @@ void stm32_main(uint32_t reset_mode) { #if MICROPY_HW_ENABLE_USB // init USB device to default setting if it was not already configured if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) { - pyb_usb_dev_init(USBD_VID, USBD_PID_CDC_MSC, USBD_MODE_CDC_MSC, NULL); + pyb_usb_dev_init(USBD_VID, USBD_PID_CDC_MSC, USBD_MODE_CDC_MSC, 0, NULL, NULL); } #endif diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 1582654115f82..3e432fc8e540d 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -120,7 +120,7 @@ void pyb_usb_init0(void) { pyb_usb_vcp_init0(); } -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info) { usb_device_t *usb_dev = &usb_device; if (!usb_dev->enabled) { // only init USB once in the device's power-lifetime @@ -146,18 +146,22 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInf } // Configure the MSC interface - const void *lu[1]; - switch (pyb_usb_storage_medium) { - #if MICROPY_HW_ENABLE_SDCARD - case PYB_USB_STORAGE_MEDIUM_SDCARD: - lu[0] = &pyb_sdcard_type; - break; - #endif - default: - lu[0] = &pyb_flash_type; - break; + const void *msc_unit_default[1]; + if (msc_n == 0) { + msc_n = 1; + msc_unit = msc_unit_default; + switch (pyb_usb_storage_medium) { + #if MICROPY_HW_ENABLE_SDCARD + case PYB_USB_STORAGE_MEDIUM_SDCARD: + msc_unit_default[0] = &pyb_sdcard_type; + break; + #endif + default: + msc_unit_default[0] = &pyb_flash_type; + break; + } } - usbd_msc_init_lu(1, lu); + usbd_msc_init_lu(msc_n, msc_unit); USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops); // start the USB device @@ -226,11 +230,12 @@ usbd_cdc_itf_t *usb_vcp_get(int idx) { */ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_vid, ARG_pid, ARG_hid, ARG_high_speed }; + enum { ARG_mode, ARG_vid, ARG_pid, ARG_msc, ARG_hid, ARG_high_speed }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_vid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = USBD_VID} }, { MP_QSTR_pid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_msc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_empty_tuple_obj)} }, { MP_QSTR_hid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&pyb_usb_hid_mouse_obj)} }, #if USBD_SUPPORT_HS_MODE { MP_QSTR_high_speed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, @@ -347,6 +352,30 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * goto bad_mode; } + // Get MSC logical units + size_t msc_n = 0; + const void *msc_unit[USBD_MSC_MAX_LUN]; + if (mode & USBD_MODE_IFACE_MSC) { + mp_obj_t *items; + mp_obj_get_array(args[ARG_msc].u_obj, &msc_n, &items); + if (msc_n > USBD_MSC_MAX_LUN) { + mp_raise_ValueError("too many logical units"); + } + for (size_t i = 0; i < msc_n; ++i) { + mp_obj_type_t *type = mp_obj_get_type(items[i]); + if (type == &pyb_flash_type + || type == &pyb_sdcard_type + #if MICROPY_HW_ENABLE_MMCARD + || type == &pyb_mmcard_type + #endif + ) { + msc_unit[i] = type; + } else { + mp_raise_ValueError("unsupported logical unit"); + } + } + } + // get hid info if user selected such a mode USBD_HID_ModeInfoTypeDef hid_info; if (mode & USBD_MODE_IFACE_HID) { @@ -372,7 +401,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * #endif // init the USB device - if (!pyb_usb_dev_init(vid, pid, mode, &hid_info)) { + if (!pyb_usb_dev_init(vid, pid, mode, msc_n, msc_unit, &hid_info)) { goto bad_mode; } diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 0aa50f9e77772..b1c8b476a7d8e 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -66,7 +66,7 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated void pyb_usb_init0(void); -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info); +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info); void pyb_usb_dev_deinit(void); bool usb_vcp_is_enabled(void); int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0 diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c index 0148fc7c6c2d0..1f9f68ed88dea 100644 --- a/ports/stm32/usbd_msc_interface.c +++ b/ports/stm32/usbd_msc_interface.c @@ -33,8 +33,6 @@ #include "storage.h" #include "sdcard.h" -#define USBD_MSC_MAX_LUN (2) - // This flag is needed to support removal of the medium, so that the USB drive // can be unmounted and won't be remounted automatically. #define FLAGS_STARTED (0x01) diff --git a/ports/stm32/usbd_msc_interface.h b/ports/stm32/usbd_msc_interface.h index 9d25a72a3a4ba..411c707cab7df 100644 --- a/ports/stm32/usbd_msc_interface.h +++ b/ports/stm32/usbd_msc_interface.h @@ -26,6 +26,8 @@ #ifndef MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H #define MICROPY_INCLUDED_STM32_USBD_MSC_INTERFACE_H +#define USBD_MSC_MAX_LUN (2) + extern const USBD_StorageTypeDef usbd_msc_fops; void usbd_msc_init_lu(size_t lu_n, const void *lu_data); From 8b18cfedee441413d6b53a3d7c083a1e3a1a47e6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 11 Jun 2019 21:01:14 +1000 Subject: [PATCH 0170/1299] stm32/usbd_msc: Allow to compile when USB enabled and SD card disabled. --- ports/stm32/usb.c | 2 ++ ports/stm32/usbd_msc_interface.c | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 3e432fc8e540d..2807d512bee17 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -364,7 +364,9 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * for (size_t i = 0; i < msc_n; ++i) { mp_obj_type_t *type = mp_obj_get_type(items[i]); if (type == &pyb_flash_type + #if MICROPY_HW_ENABLE_SDCARD || type == &pyb_sdcard_type + #endif #if MICROPY_HW_ENABLE_MMCARD || type == &pyb_mmcard_type #endif diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c index 1f9f68ed88dea..aa2b381a09ee7 100644 --- a/ports/stm32/usbd_msc_interface.c +++ b/ports/stm32/usbd_msc_interface.c @@ -135,6 +135,7 @@ STATIC int lu_ioctl(uint8_t lun, int op, uint32_t *data) { default: return -1; } + #if MICROPY_HW_ENABLE_SDCARD } else if (lu == &pyb_sdcard_type #if MICROPY_HW_ENABLE_MMCARD || lu == &pyb_mmcard_type @@ -158,6 +159,7 @@ STATIC int lu_ioctl(uint8_t lun, int op, uint32_t *data) { default: return -1; } + #endif } else { return -1; } @@ -205,12 +207,13 @@ STATIC int usbd_msc_Inquiry(uint8_t lun, const uint8_t *params, uint8_t *data_ou if (lun >= usbd_msc_lu_num) { return -1; } - const void *lu = usbd_msc_lu_data[lun]; uint8_t alloc_len = params[3] << 8 | params[4]; int len = MIN(sizeof(usbd_msc_inquiry_data), alloc_len); memcpy(data_out, usbd_msc_inquiry_data, len); + #if MICROPY_HW_ENABLE_SDCARD + const void *lu = usbd_msc_lu_data[lun]; if (len == sizeof(usbd_msc_inquiry_data)) { if (lu == &pyb_sdcard_type) { memcpy(data_out + 24, "SDCard", sizeof("SDCard") - 1); @@ -221,6 +224,7 @@ STATIC int usbd_msc_Inquiry(uint8_t lun, const uint8_t *params, uint8_t *data_ou } #endif } + #endif return len; } @@ -282,6 +286,7 @@ STATIC int8_t usbd_msc_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16 if (lu == &pyb_flash_type) { storage_read_blocks(buf, blk_addr, blk_len); return 0; + #if MICROPY_HW_ENABLE_SDCARD } else if (lu == &pyb_sdcard_type #if MICROPY_HW_ENABLE_MMCARD || lu == &pyb_mmcard_type @@ -290,6 +295,7 @@ STATIC int8_t usbd_msc_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16 if (sdcard_read_blocks(buf, blk_addr, blk_len) == 0) { return 0; } + #endif } return -1; } @@ -304,6 +310,7 @@ STATIC int8_t usbd_msc_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint1 if (lu == &pyb_flash_type) { storage_write_blocks(buf, blk_addr, blk_len); return 0; + #if MICROPY_HW_ENABLE_SDCARD } else if (lu == &pyb_sdcard_type #if MICROPY_HW_ENABLE_MMCARD || lu == &pyb_mmcard_type @@ -312,6 +319,7 @@ STATIC int8_t usbd_msc_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint1 if (sdcard_write_blocks(buf, blk_addr, blk_len) == 0) { return 0; } + #endif } return -1; } From 14cf91f70467aa928f3e17223f108ace0864b4fe Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 15 May 2019 00:43:38 +1000 Subject: [PATCH 0171/1299] stm32: In link script, define start of stack separately from heap end. Previously the end of the heap was the start (lowest address) of the stack. With the changes in this commit these addresses are now independent, allowing a board to place the heap and stack in separate locations. --- ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 8 ++++---- ports/stm32/boards/PYBD_SF6/f767.ld | 8 ++++---- ports/stm32/boards/STM32F769DISC/f769_qspi.ld | 6 ++++-- ports/stm32/boards/stm32f091xc.ld | 8 ++++---- ports/stm32/boards/stm32f401xd.ld | 10 +++++----- ports/stm32/boards/stm32f401xe.ld | 8 ++++---- ports/stm32/boards/stm32f405.ld | 8 ++++---- ports/stm32/boards/stm32f411.ld | 8 ++++---- ports/stm32/boards/stm32f413xg.ld | 8 ++++---- ports/stm32/boards/stm32f413xh.ld | 8 ++++---- ports/stm32/boards/stm32f429.ld | 8 ++++---- ports/stm32/boards/stm32f439.ld | 6 ++++-- ports/stm32/boards/stm32f722.ld | 8 ++++---- ports/stm32/boards/stm32f746.ld | 10 +++++----- ports/stm32/boards/stm32f767.ld | 8 ++++---- ports/stm32/boards/stm32f769.ld | 8 ++++---- ports/stm32/boards/stm32h743.ld | 8 ++++---- ports/stm32/boards/stm32l432.ld | 8 ++++---- ports/stm32/boards/stm32l476xe.ld | 8 ++++---- ports/stm32/boards/stm32l476xg.ld | 8 ++++---- ports/stm32/boards/stm32l496xg.ld | 8 ++++---- ports/stm32/gccollect.h | 1 + ports/stm32/main.c | 2 +- ports/stm32/modmachine.c | 1 + ports/stm32/pybthread.c | 4 ++-- ports/stm32/stm32_it.c | 2 +- 26 files changed, 92 insertions(+), 86 deletions(-) diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index 49b46bce50d6e..e9d6fa3c39b21 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -29,16 +29,16 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _ram_end - 16K; /* 16k stack */ +_heap_end = _sstack; ENTRY(Reset_Handler) diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld index 7f13eb45fe541..2a474fba07b6d 100644 --- a/ports/stm32/boards/PYBD_SF6/f767.ld +++ b/ports/stm32/boards/PYBD_SF6/f767.ld @@ -28,16 +28,16 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 24K; /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _ram_end - 24K; /* 24k stack */ +_heap_end = _sstack; ENTRY(Reset_Handler) diff --git a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld index eb2cf783eb67b..362fab3305c46 100644 --- a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld +++ b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld @@ -27,14 +27,16 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20078000; /* tunable */ +_heap_end = _sstack; ENTRY(Reset_Handler) diff --git a/ports/stm32/boards/stm32f091xc.ld b/ports/stm32/boards/stm32f091xc.ld index 73b8442957dc9..5e1e9e7bd35d6 100644 --- a/ports/stm32/boards/stm32f091xc.ld +++ b/ports/stm32/boards/stm32f091xc.ld @@ -14,13 +14,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 6K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20006800; /* room for a 6k stack */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f401xd.ld b/ports/stm32/boards/stm32f401xd.ld index 7c0e790185620..50cb3c571b5da 100644 --- a/ports/stm32/boards/stm32f401xd.ld +++ b/ports/stm32/boards/stm32f401xd.ld @@ -14,15 +14,15 @@ MEMORY /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; -_minimum_heap_size = 16K; +_minimum_heap_size = 16K; /* tunable */ -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20014000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f401xe.ld b/ports/stm32/boards/stm32f401xe.ld index e76bbad1c2dee..78e0dc1cbaf48 100644 --- a/ports/stm32/boards/stm32f401xe.ld +++ b/ports/stm32/boards/stm32f401xe.ld @@ -16,13 +16,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20014000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f405.ld b/ports/stm32/boards/stm32f405.ld index 0375491f65aae..13133e8c6d580 100644 --- a/ports/stm32/boards/stm32f405.ld +++ b/ports/stm32/boards/stm32f405.ld @@ -17,13 +17,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2001c000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f411.ld b/ports/stm32/boards/stm32f411.ld index 9e3e6bc154650..8ae5f6929ccf9 100644 --- a/ports/stm32/boards/stm32f411.ld +++ b/ports/stm32/boards/stm32f411.ld @@ -16,13 +16,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2001c000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f413xg.ld b/ports/stm32/boards/stm32f413xg.ld index cac313bc673ae..c2719b834f3ef 100644 --- a/ports/stm32/boards/stm32f413xg.ld +++ b/ports/stm32/boards/stm32f413xg.ld @@ -19,13 +19,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _ram_end - 16K; /* 240K, tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f413xh.ld b/ports/stm32/boards/stm32f413xh.ld index f6dc430e322ff..017dbbac17292 100644 --- a/ports/stm32/boards/stm32f413xh.ld +++ b/ports/stm32/boards/stm32f413xh.ld @@ -19,13 +19,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _ram_end - 16K; /* 240K, tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f429.ld b/ports/stm32/boards/stm32f429.ld index d91f625ef6735..35d0736eefd7b 100644 --- a/ports/stm32/boards/stm32f429.ld +++ b/ports/stm32/boards/stm32f429.ld @@ -17,13 +17,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2002c000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f439.ld b/ports/stm32/boards/stm32f439.ld index 16c606eccc94c..2b51c3a371a47 100644 --- a/ports/stm32/boards/stm32f439.ld +++ b/ports/stm32/boards/stm32f439.ld @@ -18,11 +18,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* top end of the stack */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2002c000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f722.ld b/ports/stm32/boards/stm32f722.ld index f2a1d8511728a..8986c68d526c8 100644 --- a/ports/stm32/boards/stm32f722.ld +++ b/ports/stm32/boards/stm32f722.ld @@ -15,13 +15,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20038000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f746.ld b/ports/stm32/boards/stm32f746.ld index b5864453dd031..330dd97141b6e 100644 --- a/ports/stm32/boards/stm32f746.ld +++ b/ports/stm32/boards/stm32f746.ld @@ -1,5 +1,5 @@ /* - GNU linker script for STM32F405 + GNU linker script for STM32F746 */ /* Specify the memory areas */ @@ -17,13 +17,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2004c000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f767.ld b/ports/stm32/boards/stm32f767.ld index c05fd8021b079..47e992c2dd327 100644 --- a/ports/stm32/boards/stm32f767.ld +++ b/ports/stm32/boards/stm32f767.ld @@ -18,13 +18,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20078000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32f769.ld b/ports/stm32/boards/stm32f769.ld index d6da439435903..41bb321a3766a 100644 --- a/ports/stm32/boards/stm32f769.ld +++ b/ports/stm32/boards/stm32f769.ld @@ -17,13 +17,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20078000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32h743.ld b/ports/stm32/boards/stm32h743.ld index ca429edb7be17..0f1c2b777e953 100644 --- a/ports/stm32/boards/stm32h743.ld +++ b/ports/stm32/boards/stm32h743.ld @@ -17,13 +17,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define tho top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2407C000; /* tunable */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32l432.ld b/ports/stm32/boards/stm32l432.ld index 70956c95bef69..40515e75b33b8 100644 --- a/ports/stm32/boards/stm32l432.ld +++ b/ports/stm32/boards/stm32l432.ld @@ -15,13 +15,13 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 6K; /* tunable */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2000A800; /* room for a 6k stack */ +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32l476xe.ld b/ports/stm32/boards/stm32l476xe.ld index 31929517d77f6..330ec96e67bbc 100644 --- a/ports/stm32/boards/stm32l476xe.ld +++ b/ports/stm32/boards/stm32l476xe.ld @@ -18,10 +18,10 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_fs_cache_start = ORIGIN(FS_CACHE); @@ -29,7 +29,7 @@ _ram_fs_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20014000; /* tunable */ +_heap_end = _sstack; _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32l476xg.ld b/ports/stm32/boards/stm32l476xg.ld index 59c5d90b69aca..7983fb39a1f3e 100644 --- a/ports/stm32/boards/stm32l476xg.ld +++ b/ports/stm32/boards/stm32l476xg.ld @@ -18,10 +18,10 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM); +_sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ _ram_fs_cache_start = ORIGIN(FS_CACHE); @@ -29,7 +29,7 @@ _ram_fs_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x20014000; /* tunable */ +_heap_end = _sstack; _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32l496xg.ld b/ports/stm32/boards/stm32l496xg.ld index b42087319964e..e1ceb50707363 100644 --- a/ports/stm32/boards/stm32l496xg.ld +++ b/ports/stm32/boards/stm32l496xg.ld @@ -18,10 +18,10 @@ MEMORY _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the top end of the stack. The stack is full descending so begins just - above last byte of RAM. Note that EABI requires the stack to be 8-byte - aligned for a call. */ +/* Define the stack. The stack is full descending so begins just above last byte + of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ _estack = ORIGIN(RAM) + LENGTH(RAM) + LENGTH(SRAM2); +_sstack = _estack - 206K; /* tunable */ /* RAM extents for the garbage collector */ _ram_fs_cache_start = ORIGIN(FS_CACHE); @@ -29,7 +29,7 @@ _ram_fs_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM) + LENGTH(SRAM2); _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = 0x2001C000; /* tunable */ +_heap_end = _sstack; _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/gccollect.h b/ports/stm32/gccollect.h index 25a74a306a939..4992a96897e40 100644 --- a/ports/stm32/gccollect.h +++ b/ports/stm32/gccollect.h @@ -37,6 +37,7 @@ extern uint32_t _sbss; extern uint32_t _ebss; extern uint32_t _heap_start; extern uint32_t _heap_end; +extern uint32_t _sstack; extern uint32_t _estack; extern uint32_t _ram_end; diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 44e29921b1c84..523034e097638 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -536,7 +536,7 @@ void stm32_main(uint32_t reset_mode) { // to recover from limit hit. (Limit is measured in bytes.) // Note: stack control relies on main thread being initialised above mp_stack_set_top(&_estack); - mp_stack_set_limit((char*)&_estack - (char*)&_heap_end - 1024); + mp_stack_set_limit((char*)&_estack - (char*)&_sstack - 1024); // GC init gc_init(MICROPY_HEAP_START, MICROPY_HEAP_END); diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index eca8322eac4ca..cf615ea6aa381 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -174,6 +174,7 @@ STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) { printf("_edata=%p\n", &_edata); printf("_sbss=%p\n", &_sbss); printf("_ebss=%p\n", &_ebss); + printf("_sstack=%p\n", &_sstack); printf("_estack=%p\n", &_estack); printf("_ram_start=%p\n", &_ram_start); printf("_heap_start=%p\n", &_heap_start); diff --git a/ports/stm32/pybthread.c b/ports/stm32/pybthread.c index 6baf88f66b25a..d6e9a3f515017 100644 --- a/ports/stm32/pybthread.c +++ b/ports/stm32/pybthread.c @@ -70,8 +70,8 @@ void pyb_thread_init(pyb_thread_t *thread) { thread->sp = NULL; // will be set when this thread switches out thread->local_state = 0; // will be set by mp_thread_init thread->arg = NULL; - thread->stack = &_heap_end; - thread->stack_len = ((uint32_t)&_estack - (uint32_t)&_heap_end) / sizeof(uint32_t); + thread->stack = &_sstack; + thread->stack_len = ((uint32_t)&_estack - (uint32_t)&_sstack) / sizeof(uint32_t); thread->all_next = NULL; thread->run_prev = thread; thread->run_next = thread; diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 078b143bbd35d..0c5263e0537ca 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -181,7 +181,7 @@ void HardFault_C_Handler(ExceptionRegisters_t *regs) { if ((void*)&_ram_start <= (void*)regs && (void*)regs < (void*)&_ram_end) { mp_hal_stdout_tx_str("Stack:\r\n"); uint32_t *stack_top = &_estack; - if ((void*)regs < (void*)&_heap_end) { + if ((void*)regs < (void*)&_sstack) { // stack not in static stack area so limit the amount we print stack_top = (uint32_t*)regs + 32; } From 637aa9784dc96301cfa5c4ccdd0ab1ae7bad5744 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Fri, 14 Jun 2019 22:22:03 +0200 Subject: [PATCH 0172/1299] esp8266/uart: Fix invalid ringbuf name when event driven REPL enabled. --- ports/esp8266/uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp8266/uart.c b/ports/esp8266/uart.c index cf9e8f61b230f..61715f5ce1a37 100644 --- a/ports/esp8266/uart.c +++ b/ports/esp8266/uart.c @@ -301,7 +301,7 @@ void uart_task_handler(os_event_t *evt) { } int c, ret = 0; - while ((c = ringbuf_get(&input_buf)) >= 0) { + while ((c = ringbuf_get(&stdin_ringbuf)) >= 0) { if (c == mp_interrupt_char) { mp_keyboard_interrupt(); } From 1a51fc9ddf889c6a81e0156e6d438e4228479874 Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Sun, 16 Jun 2019 11:57:54 -0600 Subject: [PATCH 0173/1299] esp32/machine_sdcard: Fix bug in SPI slot number selection. And fix minor typo in docs when referring to SDCard class. --- docs/library/machine.SDCard.rst | 2 +- ports/esp32/machine_sdcard.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/library/machine.SDCard.rst b/docs/library/machine.SDCard.rst index 34bb2e48bf38d..8398624c15c19 100644 --- a/docs/library/machine.SDCard.rst +++ b/docs/library/machine.SDCard.rst @@ -30,7 +30,7 @@ vary from platform to platform. The class implements the block protocol defined by :class:`uos.AbstractBlockDev`. This allows the mounting of an SD card to be as simple as:: - uos.mount(storage.SDCard(), "/sd") + uos.mount(machine.SDCard(), "/sd") The constrcutor takes the following paramters: diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 633d4031d6ec1..1400c56f35237 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -203,7 +203,6 @@ STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args if (is_spi) { self->host.slot = slot_num ? HSPI_HOST : VSPI_HOST; - slot_num -= 2; } DEBUG_printf(" Calling host.init()"); From 3ee3995be1c6c461110d7908498777241e08a76a Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 17 Jun 2019 18:27:29 +1000 Subject: [PATCH 0174/1299] esp32: Update to use ESP IDF v3.3-beta3. This updates ESP IDF to use v3.3-beta3. And also adjusts README.md to point to stable docs which provide a link to download the correct toolchain for this IDF version, namely 1.22.0-80-g6c4433a-5.2.0 --- ports/esp32/Makefile | 26 ++++++++++++++++++-------- ports/esp32/README.md | 6 +++--- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 98ad196c1d235..67e2f52415d3b 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -27,7 +27,7 @@ SDKCONFIG ?= boards/sdkconfig SDKCONFIG_H = $(BUILD)/sdkconfig.h # the git hash of the currently supported ESP IDF version -ESPIDF_SUPHASH := 5c88c5996dbde6208e3bec05abc21ff6cd822d26 +ESPIDF_SUPHASH := 6b3da6b1882f3b72e904cc90be67e9c4e3f369a9 # paths to ESP IDF and its components ifeq ($(ESPIDF),) @@ -78,7 +78,10 @@ INC_ESPCOMP += -I$(ESPCOMP)/driver/include INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes +INC_ESPCOMP += -I$(ESPCOMP)/efuse/include +INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include INC_ESPCOMP += -I$(ESPCOMP)/soc/include INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include @@ -134,7 +137,7 @@ LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority -u ld_include_panic_high LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a LDFLAGS += -L$(ESPCOMP)/esp32/ld LDFLAGS += -T $(BUILD)/esp32_out.ld -LDFLAGS += -T $(BUILD)/esp32.common.ld +LDFLAGS += -T $(BUILD)/esp32.project.ld LDFLAGS += -T esp32.rom.ld LDFLAGS += -T esp32.rom.libgcc.ld LDFLAGS += -T esp32.peripherals.ld @@ -269,6 +272,12 @@ ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\ rtc_module.o \ ) +ESPIDF_EFUSE_O = $(addprefix $(ESPCOMP)/efuse/,\ + esp32/esp_efuse_table.o \ + src/esp_efuse_api.o \ + src/esp_efuse_utility.o \ + ) + $(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ brownout.o \ @@ -276,6 +285,7 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ coexist.o \ dbg_stubs.o \ dport_panic_highint_hdl.o \ + esp_adapter.o \ esp_err_to_name.o \ esp_himem.o \ panic.o \ @@ -291,7 +301,6 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ task_wdt.o \ cache_err_int.o \ clk.o \ - core_dump.o \ cpu_start.o \ gdbstub.o \ crosscore_int.o \ @@ -310,7 +319,6 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ intr_alloc.o \ dport_access.o \ wifi_init.o \ - wifi_os_adapter.o \ sleep_modes.o \ spiram.o \ spiram_psram.o \ @@ -685,6 +693,7 @@ ESPIDF_SDMMC_O = $(addprefix $(ESPCOMP)/sdmmc/,\ OBJ_ESPIDF = OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_DRIVER_O)) +OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_EFUSE_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP32_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP_RINGBUF_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_HEAP_O)) @@ -716,6 +725,7 @@ $(OBJ_ESPIDF): $(SDKCONFIG_H) LIB_ESPIDF = LIB_ESPIDF += driver +LIB_ESPIDF += efuse LIB_ESPIDF += esp32 LIB_ESPIDF += esp_ringbuf LIB_ESPIDF += heap @@ -757,6 +767,7 @@ $(BUILD_ESPIDF_LIB)/$(1)/lib$(1).a: $(addprefix $$(BUILD)/,$(2)) endef $(eval $(call gen_espidf_lib_rule,driver,$(ESPIDF_DRIVER_O))) +$(eval $(call gen_espidf_lib_rule,efuse,$(ESPIDF_EFUSE_O))) $(eval $(call gen_espidf_lib_rule,esp32,$(ESPIDF_ESP32_O))) $(eval $(call gen_espidf_lib_rule,esp_ringbuf,$(ESPIDF_ESP_RINGBUF_O))) $(eval $(call gen_espidf_lib_rule,heap,$(ESPIDF_HEAP_O))) @@ -804,7 +815,7 @@ $(eval $(foreach lib,$(LIB_ESPIDF),$(eval $(call gen_sections_info_rule,$(BUILD_ $(LDGEN_SECTION_INFOS): $(LDGEN_SECTIONS_INFO) $(ESPIDF)/make/ldgen.mk $(Q)printf "$(foreach info,$(LDGEN_SECTIONS_INFO),$(info)\n)" > $@ -$(BUILD)/esp32.common.ld: $(ESPCOMP)/esp32/ld/esp32.common.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG) $(LDGEN_SECTION_INFOS) +$(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG) $(LDGEN_SECTION_INFOS) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ --input $< \ @@ -864,7 +875,7 @@ $(BUILD)/application.bin: $(BUILD)/application.elf $(ECHO) "Create $@" $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< -$(BUILD)/application.elf: $(OBJ) $(LIB) $(BUILD)/esp32_out.ld $(BUILD)/esp32.common.ld +$(BUILD)/application.elf: $(OBJ) $(LIB) $(BUILD)/esp32_out.ld $(BUILD)/esp32.project.ld $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS) $(Q)$(SIZE) $@ @@ -891,7 +902,7 @@ $(BUILD)/%.o: %.cpp BOOTLOADER_LIB_DIR = $(BUILD)/bootloader BOOTLOADER_LIB_ALL = -$(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/micro-ecc/micro-ecc -I$(ESPCOMP)/esp32 -Wno-error=format +$(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/micro-ecc/micro-ecc -I$(ESPCOMP)/efuse/include -I$(ESPCOMP)/esp32 -Wno-error=format # libbootloader_support.a BOOTLOADER_LIB_ALL += bootloader_support @@ -903,7 +914,6 @@ BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOM bootloader_support/src/bootloader_random.o \ bootloader_support/src/bootloader_sha.o \ bootloader_support/src/bootloader_utility.o \ - bootloader_support/src/efuse.o \ bootloader_support/src/flash_qio_mode.o \ bootloader_support/src/secure_boot_signatures.o \ bootloader_support/src/secure_boot.o \ diff --git a/ports/esp32/README.md b/ports/esp32/README.md index cd3d5af198407..12144d822d9ad 100644 --- a/ports/esp32/README.md +++ b/ports/esp32/README.md @@ -37,9 +37,9 @@ git hash of this version can be found by running `make` without a configured The binary toolchain (binutils, gcc, etc.) can be installed using the following guides: - * [Linux installation](https://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html) - * [MacOS installation](https://esp-idf.readthedocs.io/en/latest/get-started/macos-setup.html) - * [Windows installation](https://esp-idf.readthedocs.io/en/latest/get-started/windows-setup.html) + * [Linux installation](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/linux-setup.html) + * [MacOS installation](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/macos-setup.html) + * [Windows installation](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/windows-setup.html) If you are on a Windows machine then the [Windows Subsystem for Linux](https://msdn.microsoft.com/en-au/commandline/wsl/install_guide) From 34c04d2319cdfae01ed7bf7f9e341d69b86d751a Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 17 Jun 2019 23:19:34 +1000 Subject: [PATCH 0175/1299] py/nlrthumb: Save and restore VFP registers s16-s21 when CPU has them. These s16-s21 registers are used by gcc so need to be saved. Future versions of gcc (beyond v9.1.0), or other compilers, may eventually need additional registers saved/restored. See issue #4844. --- py/nlr.h | 9 ++++++++- py/nlrthumb.c | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/py/nlr.h b/py/nlr.h index 90595a12d37dc..8ce5cf0f4c41e 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -54,7 +54,14 @@ #endif #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) #define MICROPY_NLR_THUMB (1) - #define MICROPY_NLR_NUM_REGS (10) + #if defined(__SOFTFP__) + #define MICROPY_NLR_NUM_REGS (10) + #else + // With hardware FP registers s16-s31 are callee save so in principle + // should be saved and restored by the NLR code. gcc only uses s16-s21 + // so only save/restore those as an optimisation. + #define MICROPY_NLR_NUM_REGS (10 + 6) + #endif #elif defined(__xtensa__) #define MICROPY_NLR_XTENSA (1) #define MICROPY_NLR_NUM_REGS (10) diff --git a/py/nlrthumb.c b/py/nlrthumb.c index 99061e62cd425..32fa6b1176436 100644 --- a/py/nlrthumb.c +++ b/py/nlrthumb.c @@ -63,6 +63,11 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { "str r10, [r0, #36] \n" // store r10 into nlr_buf "str r11, [r0, #40] \n" // store r11 into nlr_buf "str r13, [r0, #44] \n" // store r13=sp into nlr_buf + #if MICROPY_NLR_NUM_REGS == 16 + "vstr d8, [r0, #48] \n" // store s16-s17 into nlr_buf + "vstr d9, [r0, #56] \n" // store s18-s19 into nlr_buf + "vstr d10, [r0, #64] \n" // store s20-s21 into nlr_buf + #endif "str lr, [r0, #8] \n" // store lr into nlr_buf #endif @@ -116,6 +121,11 @@ NORETURN void nlr_jump(void *val) { "ldr r10, [r0, #36] \n" // load r10 from nlr_buf "ldr r11, [r0, #40] \n" // load r11 from nlr_buf "ldr r13, [r0, #44] \n" // load r13=sp from nlr_buf + #if MICROPY_NLR_NUM_REGS == 16 + "vldr d8, [r0, #48] \n" // load s16-s17 from nlr_buf + "vldr d9, [r0, #56] \n" // load s18-s19 from nlr_buf + "vldr d10, [r0, #64] \n" // load s20-s21 from nlr_buf + #endif "ldr lr, [r0, #8] \n" // load lr from nlr_buf #endif "movs r0, #1 \n" // return 1, non-local return From b80bccccffea7aab68d4af9580664f77fecc45b2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 12 Jun 2019 18:03:18 +1000 Subject: [PATCH 0176/1299] esp32/modnetwork: Still try to reconnect to WLAN even with AUTH_FAIL. WIFI_REASON_AUTH_FAIL does not necessarily mean the password is wrong, and a wrong password may not lead to a WIFI_REASON_AUTH_FAIL error code. So to improve reliability connecting to a WLAN always reconnect regardless of the error. --- ports/esp32/modnetwork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index b93715b6e6433..84625760587cb 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -159,8 +159,8 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) { message = "\nno AP found"; break; case WIFI_REASON_AUTH_FAIL: + // Password may be wrong, or it just failed to connect; try to reconnect. message = "\nauthentication failed"; - wifi_sta_connect_requested = false; break; default: // Let other errors through and try to reconnect. From 5da60ff9cba990f239bdac2cd7ecdb2f84df4d63 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 24 Jun 2019 17:48:28 +1000 Subject: [PATCH 0177/1299] stm32/boards: Enable ussl module via mbedtls for boards with network. --- ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk | 2 ++ ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk | 2 ++ ports/stm32/boards/STM32F769DISC/mpconfigboard.mk | 2 ++ ports/stm32/boards/STM32F7DISC/mpconfigboard.mk | 2 ++ 4 files changed, 8 insertions(+) diff --git a/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk index e542d1c9985d3..47b4432893c89 100644 --- a/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk @@ -7,3 +7,5 @@ TEXT1_ADDR = 0x08020000 # MicroPython settings MICROPY_PY_LWIP = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 diff --git a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk index c3f12998c3ed7..0fdc1a6dcd17f 100644 --- a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk @@ -8,3 +8,5 @@ TEXT1_ADDR = 0x08020000 # MicroPython settings MICROPY_PY_LWIP = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 diff --git a/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk b/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk index 49b318d30b826..04f208c5b7f78 100644 --- a/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk +++ b/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk @@ -39,3 +39,5 @@ endif # MicroPython settings MICROPY_PY_LWIP = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 diff --git a/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk b/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk index 4f88a139e7450..8b54dc84e113e 100644 --- a/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk +++ b/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk @@ -7,3 +7,5 @@ TEXT1_ADDR = 0x08020000 # MicroPython settings MICROPY_PY_LWIP = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 From 205c6d0dc94ef1ca11d7bcef2090ef49c2015e48 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 24 Jun 2019 21:59:58 +1000 Subject: [PATCH 0178/1299] stm32/Makefile: Print info messages about use of mboot/QSPI flash. --- ports/stm32/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 4c9a2342ca8c2..31597e88a589b 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -513,6 +513,12 @@ $(BUILD)/firmware.elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LDFLAGS_MOD) $(LIBS) $(Q)$(SIZE) $@ +ifneq ($(TEXT0_ADDR),0x08000000) + $(ECHO) "INFO: this build requires mboot to be installed first" +endif +ifeq ($(TEXT1_ADDR),0x90000000) + $(ECHO) "INFO: this build places firmware in external QSPI flash" +endif PLLVALUES = boards/pllvalues.py MAKE_PINS = boards/make-pins.py From 04c7cdb668cc7ee391ef5fe000f825389197f7e2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 22 Jun 2019 21:26:03 +1000 Subject: [PATCH 0179/1299] stm32: Enter bootloader via a system reset. Entering a bootloader (ST system bootloader, or custom mboot) from software by directly branching to it is not reliable, and the reliability of it working can depend on the peripherals that were enabled by the application code. It's also not possible to branch to a bootloader if the WDT is enabled (unless the bootloader has specific provisions to feed the WDT). This patch changes the way a bootloader is entered from software by first doing a complete system reset, then branching to the desired bootloader early on in the start-up process. The top two words of RAM (of the stack) are reserved to store flags indicating that the bootloader should be entered after a reset. --- ports/stm32/Makefile | 1 + ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 2 +- ports/stm32/boards/PYBD_SF6/f767.ld | 2 +- ports/stm32/boards/STM32F769DISC/f769_qspi.ld | 2 +- ports/stm32/boards/stm32f091xc.ld | 2 +- ports/stm32/boards/stm32f401xd.ld | 2 +- ports/stm32/boards/stm32f401xe.ld | 2 +- ports/stm32/boards/stm32f405.ld | 2 +- ports/stm32/boards/stm32f411.ld | 2 +- ports/stm32/boards/stm32f413xg.ld | 2 +- ports/stm32/boards/stm32f413xh.ld | 2 +- ports/stm32/boards/stm32f429.ld | 2 +- ports/stm32/boards/stm32f439.ld | 2 +- ports/stm32/boards/stm32f722.ld | 2 +- ports/stm32/boards/stm32f746.ld | 2 +- ports/stm32/boards/stm32f767.ld | 2 +- ports/stm32/boards/stm32f769.ld | 2 +- ports/stm32/boards/stm32h743.ld | 2 +- ports/stm32/boards/stm32l432.ld | 2 +- ports/stm32/boards/stm32l476xe.ld | 2 +- ports/stm32/boards/stm32l476xg.ld | 2 +- ports/stm32/boards/stm32l496xg.ld | 2 +- ports/stm32/main.c | 4 ++ ports/stm32/modmachine.c | 34 ++---------- ports/stm32/powerctrl.c | 54 +++++++++++++++++++ ports/stm32/powerctrl.h | 4 ++ ports/stm32/stm32_it.c | 3 +- 27 files changed, 91 insertions(+), 51 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 31597e88a589b..153ea446262d0 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -92,6 +92,7 @@ CFLAGS += -fsingle-precision-constant -Wdouble-promotion endif LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref +LDFLAGS += --defsym=_estack_reserve=8 LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Remove uncalled code from the final image. diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index e9d6fa3c39b21..b6d3e08e30c76 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -31,7 +31,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld index 2a474fba07b6d..1dd4c11ed9898 100644 --- a/ports/stm32/boards/PYBD_SF6/f767.ld +++ b/ports/stm32/boards/PYBD_SF6/f767.ld @@ -30,7 +30,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 24K; /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld index 362fab3305c46..9a0bd56fb34d9 100644 --- a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld +++ b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld @@ -29,7 +29,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f091xc.ld b/ports/stm32/boards/stm32f091xc.ld index 5e1e9e7bd35d6..5bcc4c7275de6 100644 --- a/ports/stm32/boards/stm32f091xc.ld +++ b/ports/stm32/boards/stm32f091xc.ld @@ -16,7 +16,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 6K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f401xd.ld b/ports/stm32/boards/stm32f401xd.ld index 50cb3c571b5da..f4146abc6d728 100644 --- a/ports/stm32/boards/stm32f401xd.ld +++ b/ports/stm32/boards/stm32f401xd.ld @@ -18,7 +18,7 @@ _minimum_heap_size = 16K; /* tunable */ /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f401xe.ld b/ports/stm32/boards/stm32f401xe.ld index 78e0dc1cbaf48..e7bd8edfed1fb 100644 --- a/ports/stm32/boards/stm32f401xe.ld +++ b/ports/stm32/boards/stm32f401xe.ld @@ -18,7 +18,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f405.ld b/ports/stm32/boards/stm32f405.ld index 13133e8c6d580..b6f5d3057847a 100644 --- a/ports/stm32/boards/stm32f405.ld +++ b/ports/stm32/boards/stm32f405.ld @@ -19,7 +19,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f411.ld b/ports/stm32/boards/stm32f411.ld index 8ae5f6929ccf9..50633118eb240 100644 --- a/ports/stm32/boards/stm32f411.ld +++ b/ports/stm32/boards/stm32f411.ld @@ -18,7 +18,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f413xg.ld b/ports/stm32/boards/stm32f413xg.ld index c2719b834f3ef..96d6dc5fb0d17 100644 --- a/ports/stm32/boards/stm32f413xg.ld +++ b/ports/stm32/boards/stm32f413xg.ld @@ -21,7 +21,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f413xh.ld b/ports/stm32/boards/stm32f413xh.ld index 017dbbac17292..0b28730de53d5 100644 --- a/ports/stm32/boards/stm32f413xh.ld +++ b/ports/stm32/boards/stm32f413xh.ld @@ -21,7 +21,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f429.ld b/ports/stm32/boards/stm32f429.ld index 35d0736eefd7b..beeaa4df21237 100644 --- a/ports/stm32/boards/stm32f429.ld +++ b/ports/stm32/boards/stm32f429.ld @@ -19,7 +19,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f439.ld b/ports/stm32/boards/stm32f439.ld index 2b51c3a371a47..e847646b35ed3 100644 --- a/ports/stm32/boards/stm32f439.ld +++ b/ports/stm32/boards/stm32f439.ld @@ -20,7 +20,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f722.ld b/ports/stm32/boards/stm32f722.ld index 8986c68d526c8..ab41f0ea90ee0 100644 --- a/ports/stm32/boards/stm32f722.ld +++ b/ports/stm32/boards/stm32f722.ld @@ -17,7 +17,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f746.ld b/ports/stm32/boards/stm32f746.ld index 330dd97141b6e..0f1de2696456f 100644 --- a/ports/stm32/boards/stm32f746.ld +++ b/ports/stm32/boards/stm32f746.ld @@ -19,7 +19,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f767.ld b/ports/stm32/boards/stm32f767.ld index 47e992c2dd327..9410b9fa6b73e 100644 --- a/ports/stm32/boards/stm32f767.ld +++ b/ports/stm32/boards/stm32f767.ld @@ -20,7 +20,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32f769.ld b/ports/stm32/boards/stm32f769.ld index 41bb321a3766a..ebc6d033d9bb6 100644 --- a/ports/stm32/boards/stm32f769.ld +++ b/ports/stm32/boards/stm32f769.ld @@ -19,7 +19,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 32K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32h743.ld b/ports/stm32/boards/stm32h743.ld index 0f1c2b777e953..69738ab8b913a 100644 --- a/ports/stm32/boards/stm32h743.ld +++ b/ports/stm32/boards/stm32h743.ld @@ -19,7 +19,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32l432.ld b/ports/stm32/boards/stm32l432.ld index 40515e75b33b8..5558b13c89334 100644 --- a/ports/stm32/boards/stm32l432.ld +++ b/ports/stm32/boards/stm32l432.ld @@ -17,7 +17,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 6K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32l476xe.ld b/ports/stm32/boards/stm32l476xe.ld index 330ec96e67bbc..e4bcda1f16f12 100644 --- a/ports/stm32/boards/stm32l476xe.ld +++ b/ports/stm32/boards/stm32l476xe.ld @@ -20,7 +20,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32l476xg.ld b/ports/stm32/boards/stm32l476xg.ld index 7983fb39a1f3e..9fe83c74a4a47 100644 --- a/ports/stm32/boards/stm32l476xg.ld +++ b/ports/stm32/boards/stm32l476xg.ld @@ -20,7 +20,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM); +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; _sstack = _estack - 16K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/boards/stm32l496xg.ld b/ports/stm32/boards/stm32l496xg.ld index e1ceb50707363..c3399034220ec 100644 --- a/ports/stm32/boards/stm32l496xg.ld +++ b/ports/stm32/boards/stm32l496xg.ld @@ -20,7 +20,7 @@ _minimum_heap_size = 16K; /* Define the stack. The stack is full descending so begins just above last byte of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM) + LENGTH(SRAM2); +_estack = ORIGIN(RAM) + LENGTH(RAM) + LENGTH(SRAM2) - _estack_reserve; _sstack = _estack - 206K; /* tunable */ /* RAM extents for the garbage collector */ diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 523034e097638..2dcc09ae7a445 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -45,6 +45,7 @@ #include "systick.h" #include "pendsv.h" +#include "powerctrl.h" #include "pybthread.h" #include "gccollect.h" #include "factoryreset.h" @@ -368,6 +369,9 @@ STATIC uint update_reset_mode(uint reset_mode) { #endif void stm32_main(uint32_t reset_mode) { + // Check if bootloader should be entered instead of main application + powerctrl_check_enter_bootloader(); + // Enable caches and prefetch buffers #if defined(STM32F4) diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index cf615ea6aa381..a4ee47470b1dd 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -237,7 +237,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); // Resets the pyboard in a manner similar to pushing the external RESET button. STATIC mp_obj_t machine_reset(void) { - NVIC_SystemReset(); + powerctrl_mcu_reset(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); @@ -248,15 +248,6 @@ STATIC mp_obj_t machine_soft_reset(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); -__attribute__((naked)) void branch_to_bootloader(uint32_t r0, uint32_t addr) { - __asm volatile ( - "ldr r2, [r1, #0]\n" // get address of stack pointer - "msr msp, r2\n" // get stack pointer - "ldr r2, [r1, #4]\n" // get address of destination - "bx r2\n" // branch to bootloader - ); -} - // Activate the bootloader without BOOT* pins. STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { #if MICROPY_HW_ENABLE_USB @@ -266,24 +257,10 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) storage_flush(); #endif - #if __DCACHE_PRESENT == 1 - // Flush and disable caches before turning off peripherals (eg SDRAM) - SCB_DisableICache(); - SCB_DisableDCache(); - #endif - - HAL_RCC_DeInit(); - HAL_DeInit(); - - #if (__MPU_PRESENT == 1) - // MPU must be disabled for bootloader to function correctly - HAL_MPU_Disable(); - #endif - #if MICROPY_HW_USES_BOOTLOADER if (n_args == 0 || !mp_obj_is_true(args[0])) { // By default, with no args given, we enter the custom bootloader (mboot) - branch_to_bootloader(0x70ad0000, 0x08000000); + powerctrl_enter_bootloader(0x70ad0000, 0x08000000); } if (n_args == 1 && mp_obj_is_str_or_bytes(args[0])) { @@ -292,15 +269,14 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) const char *data = mp_obj_str_get_data(args[0], &len); void *mboot_region = (void*)*((volatile uint32_t*)0x08000000); memmove(mboot_region, data, len); - branch_to_bootloader(0x70ad0080, 0x08000000); + powerctrl_enter_bootloader(0x70ad0080, 0x08000000); } #endif #if defined(STM32F7) || defined(STM32H7) - branch_to_bootloader(0, 0x1ff00000); + powerctrl_enter_bootloader(0, 0x1ff00000); #else - __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); - branch_to_bootloader(0, 0x00000000); + powerctrl_enter_bootloader(0, 0x00000000); #endif while (1); diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index c3792be3ed7f2..2ad24260051e7 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -30,6 +30,60 @@ #include "rtc.h" #include "genhdr/pllfreqtable.h" +#if defined(STM32H7) +#define RCC_SR RSR +#define RCC_SR_SFTRSTF RCC_RSR_SFTRSTF +#define RCC_SR_RMVF RCC_RSR_RMVF +#else +#define RCC_SR CSR +#define RCC_SR_SFTRSTF RCC_CSR_SFTRSTF +#define RCC_SR_RMVF RCC_CSR_RMVF +#endif + +// Location in RAM of bootloader state (just after the top of the stack) +extern uint32_t _estack[]; +#define BL_STATE ((uint32_t*)&_estack) + +NORETURN void powerctrl_mcu_reset(void) { + BL_STATE[1] = 1; // invalidate bootloader address + #if __DCACHE_PRESENT == 1 + SCB_CleanDCache(); + #endif + NVIC_SystemReset(); +} + +NORETURN void powerctrl_enter_bootloader(uint32_t r0, uint32_t bl_addr) { + BL_STATE[0] = r0; + BL_STATE[1] = bl_addr; + #if __DCACHE_PRESENT == 1 + SCB_CleanDCache(); + #endif + NVIC_SystemReset(); +} + +static __attribute__((naked)) void branch_to_bootloader(uint32_t r0, uint32_t bl_addr) { + __asm volatile ( + "ldr r2, [r1, #0]\n" // get address of stack pointer + "msr msp, r2\n" // get stack pointer + "ldr r2, [r1, #4]\n" // get address of destination + "bx r2\n" // branch to bootloader + ); +} + +void powerctrl_check_enter_bootloader(void) { + uint32_t bl_addr = BL_STATE[1]; + BL_STATE[1] = 1; // invalidate bootloader address + if ((bl_addr & 0xfff) == 0 && (RCC->RCC_SR & RCC_SR_SFTRSTF)) { + // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader + RCC->RCC_SR = RCC_SR_RMVF; + #if defined(STM32F0) || defined(STM32F4) || defined(STM32L4) + __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); + #endif + uint32_t r0 = BL_STATE[0]; + branch_to_bootloader(r0, bl_addr); + } +} + #if !defined(STM32F0) // Assumes that PLL is used as the SYSCLK source diff --git a/ports/stm32/powerctrl.h b/ports/stm32/powerctrl.h index b26cab391cbec..6eb0342287c62 100644 --- a/ports/stm32/powerctrl.h +++ b/ports/stm32/powerctrl.h @@ -28,6 +28,10 @@ #include +NORETURN void powerctrl_mcu_reset(void); +NORETURN void powerctrl_enter_bootloader(uint32_t r0, uint32_t bl_addr); +void powerctrl_check_enter_bootloader(void); + int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai); int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2); void powerctrl_enter_stop_mode(void); diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 0c5263e0537ca..a3740d59cd91e 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -72,6 +72,7 @@ #include "stm32_it.h" #include "pendsv.h" #include "irq.h" +#include "powerctrl.h" #include "pybthread.h" #include "gccollect.h" #include "extint.h" @@ -144,7 +145,7 @@ int pyb_hard_fault_debug = 0; void HardFault_C_Handler(ExceptionRegisters_t *regs) { if (!pyb_hard_fault_debug) { - NVIC_SystemReset(); + powerctrl_mcu_reset(); } #if MICROPY_HW_ENABLE_USB From 89ebb3325b6572f61531d2f434dfb6969027c7be Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 25 Jun 2019 13:39:06 +1000 Subject: [PATCH 0180/1299] stm32/boards/pllvalues.py: Support HSx_VALUE defined without uint32_t. --- ports/stm32/boards/pllvalues.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/pllvalues.py b/ports/stm32/boards/pllvalues.py index a628dea8a9c64..4a85b5478a78a 100644 --- a/ports/stm32/boards/pllvalues.py +++ b/ports/stm32/boards/pllvalues.py @@ -137,7 +137,7 @@ def print_table(hse, valid_plls): def search_header_for_hsx_values(filename, vals): regex_inc = re.compile(r'#include "(boards/[A-Za-z0-9_./]+)"') - regex_def = re.compile(r'#define +(HSE_VALUE|HSI_VALUE) +\(\(uint32_t\)([0-9]+)\)') + regex_def = re.compile(r'#define +(HSE_VALUE|HSI_VALUE) +\((\(uint32_t\))?([0-9]+)\)') with open(filename) as f: for line in f: line = line.strip() @@ -149,7 +149,7 @@ def search_header_for_hsx_values(filename, vals): m = regex_def.match(line) if m: # Found HSE_VALUE or HSI_VALUE - val = int(m.group(2)) // 1000000 + val = int(m.group(3)) // 1000000 if m.group(1) == 'HSE_VALUE': vals[0] = val else: From f96f53cd978558dde93d136a22c7bd9a42cc6588 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 25 Jun 2019 13:40:26 +1000 Subject: [PATCH 0181/1299] stm32/boards: Add stm32??xx_hal_conf_base.h files with common settings. These are intended to be used by all boards, to reduce the size of a board's configuration. --- ports/stm32/boards/stm32f0xx_hal_conf_base.h | 90 +++++++++++++++++ ports/stm32/boards/stm32f4xx_hal_conf_base.h | 101 +++++++++++++++++++ ports/stm32/boards/stm32f7xx_hal_conf_base.h | 99 ++++++++++++++++++ ports/stm32/boards/stm32h7xx_hal_conf_base.h | 96 ++++++++++++++++++ ports/stm32/boards/stm32l4xx_hal_conf_base.h | 99 ++++++++++++++++++ 5 files changed, 485 insertions(+) create mode 100644 ports/stm32/boards/stm32f0xx_hal_conf_base.h create mode 100644 ports/stm32/boards/stm32f4xx_hal_conf_base.h create mode 100644 ports/stm32/boards/stm32f7xx_hal_conf_base.h create mode 100644 ports/stm32/boards/stm32h7xx_hal_conf_base.h create mode 100644 ports/stm32/boards/stm32l4xx_hal_conf_base.h diff --git a/ports/stm32/boards/stm32f0xx_hal_conf_base.h b/ports/stm32/boards/stm32f0xx_hal_conf_base.h new file mode 100644 index 0000000000000..9cb7761ac2ca4 --- /dev/null +++ b/ports/stm32/boards/stm32f0xx_hal_conf_base.h @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32F0XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32F0XX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32f0xx_hal_dma.h" +#include "stm32f0xx_hal_adc.h" +#include "stm32f0xx_hal_can.h" +#include "stm32f0xx_hal_cortex.h" +#include "stm32f0xx_hal_crc.h" +#include "stm32f0xx_hal_dac.h" +#include "stm32f0xx_hal_flash.h" +#include "stm32f0xx_hal_gpio.h" +#include "stm32f0xx_hal_i2c.h" +#include "stm32f0xx_hal_i2s.h" +#include "stm32f0xx_hal_iwdg.h" +#include "stm32f0xx_hal_pcd.h" +#include "stm32f0xx_hal_pwr.h" +#include "stm32f0xx_hal_rcc.h" +#include "stm32f0xx_hal_rtc.h" +#include "stm32f0xx_hal_spi.h" +#include "stm32f0xx_hal_tim.h" +#include "stm32f0xx_hal_uart.h" +#include "stm32f0xx_hal_usart.h" +#include "stm32f0xx_hal_wwdg.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define HSI_VALUE (8000000) +#define HSI48_VALUE (48000000) +#define LSI_VALUE (40000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define PREFETCH_ENABLE 1 +#define USE_RTOS 0 +#define USE_SPI_CRC 1 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32F0XX_HAL_CONF_BASE_H diff --git a/ports/stm32/boards/stm32f4xx_hal_conf_base.h b/ports/stm32/boards/stm32f4xx_hal_conf_base.h new file mode 100644 index 0000000000000..cdae0c5629e20 --- /dev/null +++ b/ports/stm32/boards/stm32f4xx_hal_conf_base.h @@ -0,0 +1,101 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32f4xx_hal_dma.h" +#include "stm32f4xx_hal_adc.h" +#include "stm32f4xx_hal_can.h" +#include "stm32f4xx_hal_cortex.h" +#include "stm32f4xx_hal_crc.h" +#include "stm32f4xx_hal_dac.h" +#include "stm32f4xx_hal_dcmi.h" +#include "stm32f4xx_hal_eth.h" +#include "stm32f4xx_hal_flash.h" +#include "stm32f4xx_hal_gpio.h" +#include "stm32f4xx_hal_hash.h" +#include "stm32f4xx_hal_hcd.h" +#include "stm32f4xx_hal_i2c.h" +#include "stm32f4xx_hal_i2s.h" +#include "stm32f4xx_hal_iwdg.h" +#include "stm32f4xx_hal_pcd.h" +#include "stm32f4xx_hal_pwr.h" +#include "stm32f4xx_hal_rcc.h" +#include "stm32f4xx_hal_rtc.h" +#include "stm32f4xx_hal_sd.h" +#include "stm32f4xx_hal_sdram.h" +#include "stm32f4xx_hal_spi.h" +#include "stm32f4xx_hal_tim.h" +#include "stm32f4xx_hal_uart.h" +#include "stm32f4xx_hal_usart.h" +#include "stm32f4xx_hal_wwdg.h" + +// Enable various HAL modules +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_ETH_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define HSI_VALUE (16000000) +#define LSI_VALUE (40000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define DATA_CACHE_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define PREFETCH_ENABLE 1 +#define USE_RTOS 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_BASE_H diff --git a/ports/stm32/boards/stm32f7xx_hal_conf_base.h b/ports/stm32/boards/stm32f7xx_hal_conf_base.h new file mode 100644 index 0000000000000..05ab10fea08ad --- /dev/null +++ b/ports/stm32/boards/stm32f7xx_hal_conf_base.h @@ -0,0 +1,99 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32f7xx_hal_dma.h" +#include "stm32f7xx_hal_adc.h" +#include "stm32f7xx_hal_can.h" +#include "stm32f7xx_hal_cortex.h" +#include "stm32f7xx_hal_crc.h" +#include "stm32f7xx_hal_dac.h" +#include "stm32f7xx_hal_dcmi.h" +#include "stm32f7xx_hal_flash.h" +#include "stm32f7xx_hal_gpio.h" +#include "stm32f7xx_hal_hash.h" +#include "stm32f7xx_hal_hcd.h" +#include "stm32f7xx_hal_i2c.h" +#include "stm32f7xx_hal_i2s.h" +#include "stm32f7xx_hal_iwdg.h" +#include "stm32f7xx_hal_mmc.h" +#include "stm32f7xx_hal_pcd.h" +#include "stm32f7xx_hal_pwr.h" +#include "stm32f7xx_hal_rcc.h" +#include "stm32f7xx_hal_rtc.h" +#include "stm32f7xx_hal_sd.h" +#include "stm32f7xx_hal_sdram.h" +#include "stm32f7xx_hal_spi.h" +#include "stm32f7xx_hal_tim.h" +#include "stm32f7xx_hal_uart.h" +#include "stm32f7xx_hal_usart.h" +#include "stm32f7xx_hal_wwdg.h" + +// Enable various HAL modules +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define HSI_VALUE (16000000) +#define LSI_VALUE (32000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define ART_ACCLERATOR_ENABLE 1 +#define USE_RTOS 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_BASE_H diff --git a/ports/stm32/boards/stm32h7xx_hal_conf_base.h b/ports/stm32/boards/stm32h7xx_hal_conf_base.h new file mode 100644 index 0000000000000..334c6df4bdc2d --- /dev/null +++ b/ports/stm32/boards/stm32h7xx_hal_conf_base.h @@ -0,0 +1,96 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32H7XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32H7XX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32h7xx_hal_dma.h" +#include "stm32h7xx_hal_adc.h" +#include "stm32h7xx_hal_cortex.h" +#include "stm32h7xx_hal_crc.h" +#include "stm32h7xx_hal_dac.h" +#include "stm32h7xx_hal_dcmi.h" +#include "stm32h7xx_hal_flash.h" +#include "stm32h7xx_hal_gpio.h" +#include "stm32h7xx_hal_hash.h" +#include "stm32h7xx_hal_hcd.h" +#include "stm32h7xx_hal_i2c.h" +#include "stm32h7xx_hal_i2s.h" +#include "stm32h7xx_hal_iwdg.h" +#include "stm32h7xx_hal_pcd.h" +#include "stm32h7xx_hal_pwr.h" +#include "stm32h7xx_hal_rcc.h" +#include "stm32h7xx_hal_rtc.h" +#include "stm32h7xx_hal_sd.h" +#include "stm32h7xx_hal_sdram.h" +#include "stm32h7xx_hal_spi.h" +#include "stm32h7xx_hal_tim.h" +#include "stm32h7xx_hal_uart.h" +#include "stm32h7xx_hal_usart.h" +#include "stm32h7xx_hal_wwdg.h" + +// Enable various HAL modules +#define HAL_ADC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define CSI_VALUE (4000000) +#define HSI_VALUE (64000000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define USE_RTOS 0 +#define USE_SD_TRANSCEIVER 0 +#define USE_SPI_CRC 1 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_BASE_H diff --git a/ports/stm32/boards/stm32l4xx_hal_conf_base.h b/ports/stm32/boards/stm32l4xx_hal_conf_base.h new file mode 100644 index 0000000000000..7e249138f566e --- /dev/null +++ b/ports/stm32/boards/stm32l4xx_hal_conf_base.h @@ -0,0 +1,99 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32l4xx_hal_dma.h" +#include "stm32l4xx_hal_adc.h" +#include "stm32l4xx_hal_can.h" +#include "stm32l4xx_hal_cortex.h" +#include "stm32l4xx_hal_crc.h" +#include "stm32l4xx_hal_dac.h" +#include "stm32l4xx_hal_dcmi.h" +#include "stm32l4xx_hal_flash.h" +#include "stm32l4xx_hal_gpio.h" +#include "stm32l4xx_hal_hash.h" +#include "stm32l4xx_hal_hcd.h" +#include "stm32l4xx_hal_i2c.h" +#include "stm32l4xx_hal_iwdg.h" +#include "stm32l4xx_hal_pcd.h" +#include "stm32l4xx_hal_pwr.h" +#include "stm32l4xx_hal_rcc.h" +#include "stm32l4xx_hal_rtc.h" +#include "stm32l4xx_hal_sd.h" +#include "stm32l4xx_hal_spi.h" +#include "stm32l4xx_hal_tim.h" +#include "stm32l4xx_hal_uart.h" +#include "stm32l4xx_hal_usart.h" +#include "stm32l4xx_hal_wwdg.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define HSI_VALUE (16000000) +#define HSI48_VALUE (48000000) +#define LSI_VALUE (32000) +#define MSI_VALUE (4000000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define DATA_CACHE_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define PREFETCH_ENABLE 1 +#define USE_SPI_CRC 0 +#define USE_RTOS 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_BASE_H From 009b1f6559fa2a621dcd35916886385327e6abc1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 25 Jun 2019 13:42:06 +1000 Subject: [PATCH 0182/1299] stm32/boards: Rework all stm32??xx_hal_conf.h files to use common code. This eliminates a lot of duplicated code in these header files. --- .../B_L475E_IOT01A/stm32l4xx_hal_conf.h | 392 +-------------- .../stm32/boards/CERB40/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/ESPRUINO_PICO/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/HYDRABUS/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/LIMIFROG/stm32l4xx_hal_conf.h | 392 +-------------- .../NETDUINO_PLUS_2/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/NUCLEO_F091RC/stm32f0xx_hal_conf.h | 322 +------------ .../boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/NUCLEO_F429ZI/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/NUCLEO_F746ZG/stm32f7xx_hal_conf.h | 438 +---------------- .../boards/NUCLEO_F767ZI/stm32f7xx_hal_conf.h | 438 +---------------- .../boards/NUCLEO_H743ZI/stm32h7xx_hal_conf.h | 445 +----------------- .../boards/NUCLEO_L432KC/stm32l4xx_hal_conf.h | 404 +--------------- .../boards/NUCLEO_L476RG/stm32l4xx_hal_conf.h | 392 +-------------- .../boards/OLIMEX_E407/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/PYBD_SF2/stm32f7xx_hal_conf.h | 75 +-- .../boards/PYBLITEV10/stm32f4xx_hal_conf.h | 420 +---------------- .../stm32/boards/PYBV10/stm32f4xx_hal_conf.h | 420 +---------------- .../stm32/boards/PYBV11/stm32f4xx_hal_conf.h | 420 +---------------- ports/stm32/boards/PYBV3/stm32f4xx_hal_conf.h | 420 +---------------- ports/stm32/boards/PYBV4/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/STM32F411DISC/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/STM32F429DISC/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/STM32F439/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/STM32F4DISC/stm32f4xx_hal_conf.h | 420 +---------------- .../boards/STM32F769DISC/stm32f7xx_hal_conf.h | 438 +---------------- .../boards/STM32F7DISC/stm32f7xx_hal_conf.h | 438 +---------------- .../boards/STM32L476DISC/stm32l4xx_hal_conf.h | 392 +-------------- .../STM32L496GDISC/stm32l4xx_hal_conf.h | 431 +---------------- 32 files changed, 492 insertions(+), 12485 deletions(-) diff --git a/ports/stm32/boards/B_L475E_IOT01A/stm32l4xx_hal_conf.h b/ports/stm32/boards/B_L475E_IOT01A/stm32l4xx_hal_conf.h index 6bfb28118a44b..fd380ab7357e2 100644 --- a/ports/stm32/boards/B_L475E_IOT01A/stm32l4xx_hal_conf.h +++ b/ports/stm32/boards/B_L475E_IOT01A/stm32l4xx_hal_conf.h @@ -1,372 +1,20 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_conf.h - * @author MCD Application Team - * @version V1.2.0 - * @date 25-November-2015 - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32l4xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_COMP_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DFSDM_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_FIREWALL_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LCD_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_OPAMP_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -/* #define HAL_SWPMI_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/* #define HAL_TSC_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ - - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal Multiple Speed oscillator (MSI) default value. - * This value is the default MSI range value after Reset. - */ -#if !defined (MSI_VALUE) - #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* MSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/** - * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/ -#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32l4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32l4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32l4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32l4xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32l4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32l4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32l4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32l4xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32l4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32l4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32l4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FIREWALL_MODULE_ENABLED - #include "stm32l4xx_hal_firewall.h" -#endif /* HAL_FIREWALL_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32l4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32l4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32l4xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32L4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H + +#include "boards/stm32l4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) +#define EXTERNAL_SAI2_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H diff --git a/ports/stm32/boards/CERB40/stm32f4xx_hal_conf.h b/ports/stm32/boards/CERB40/stm32f4xx_hal_conf.h index e71ba33697721..9719157e55cdf 100644 --- a/ports/stm32/boards/CERB40/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/CERB40/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (12000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/ESPRUINO_PICO/stm32f4xx_hal_conf.h b/ports/stm32/boards/ESPRUINO_PICO/stm32f4xx_hal_conf.h index d27e2e9ef0819..de19251e0808a 100644 --- a/ports/stm32/boards/ESPRUINO_PICO/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/ESPRUINO_PICO/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -/* #define HAL_CAN_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -/* #define HAL_DAC_MODULE_ENABLED */ -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -/* #define HAL_SD_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/HYDRABUS/stm32f4xx_hal_conf.h b/ports/stm32/boards/HYDRABUS/stm32f4xx_hal_conf.h index daf9b63ceca01..de19251e0808a 100644 --- a/ports/stm32/boards/HYDRABUS/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/HYDRABUS/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/LIMIFROG/stm32l4xx_hal_conf.h b/ports/stm32/boards/LIMIFROG/stm32l4xx_hal_conf.h index 6bfb28118a44b..fd380ab7357e2 100644 --- a/ports/stm32/boards/LIMIFROG/stm32l4xx_hal_conf.h +++ b/ports/stm32/boards/LIMIFROG/stm32l4xx_hal_conf.h @@ -1,372 +1,20 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_conf.h - * @author MCD Application Team - * @version V1.2.0 - * @date 25-November-2015 - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32l4xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_COMP_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DFSDM_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_FIREWALL_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LCD_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_OPAMP_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -/* #define HAL_SWPMI_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/* #define HAL_TSC_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ - - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal Multiple Speed oscillator (MSI) default value. - * This value is the default MSI range value after Reset. - */ -#if !defined (MSI_VALUE) - #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* MSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/** - * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/ -#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32l4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32l4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32l4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32l4xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32l4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32l4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32l4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32l4xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32l4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32l4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32l4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FIREWALL_MODULE_ENABLED - #include "stm32l4xx_hal_firewall.h" -#endif /* HAL_FIREWALL_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32l4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32l4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32l4xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32L4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H + +#include "boards/stm32l4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) +#define EXTERNAL_SAI2_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NETDUINO_PLUS_2/stm32f4xx_hal_conf.h b/ports/stm32/boards/NETDUINO_PLUS_2/stm32f4xx_hal_conf.h index 4cb5a83e456f1..f186d5a29228c 100644 --- a/ports/stm32/boards/NETDUINO_PLUS_2/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NETDUINO_PLUS_2/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (25000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F091RC/stm32f0xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F091RC/stm32f0xx_hal_conf.h index 53ea047cbd0cc..d5b2c4f7a2e72 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/stm32f0xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F091RC/stm32f0xx_hal_conf.h @@ -1,312 +1,18 @@ -/** - ****************************************************************************** - * @file stm32f0xx_hal_conf_template.h - * @author MCD Application Team - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32f0xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F0XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F0XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F0xx_HAL_CONF_H -#define __STM32F0xx_HAL_CONF_H +#include "boards/stm32f0xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -#define HAL_CEC_MODULE_ENABLED -#define HAL_COMP_MODULE_ENABLED -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_CRC_MODULE_ENABLED -#define HAL_DAC_MODULE_ENABLED -#define HAL_DMA_MODULE_ENABLED -#define HAL_FLASH_MODULE_ENABLED -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -#define HAL_IRDA_MODULE_ENABLED -#define HAL_IWDG_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -#define HAL_SMARTCARD_MODULE_ENABLED -#define HAL_SMBUS_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_TSC_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -#define HAL_USART_MODULE_ENABLED -#define HAL_WWDG_MODULE_ENABLED - -/* ######################### Oscillator Values adaptation ################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -/** - * @brief In the following line adjust the External High Speed oscillator (HSE) Startup - * Timeout value - */ -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE 8000000U /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief In the following line adjust the Internal High Speed oscillator (HSI) Startup - * Timeout value - */ -#if !defined (HSI_STARTUP_TIMEOUT) - #define HSI_STARTUP_TIMEOUT 5000U /*!< Time out for HSI start up */ -#endif /* HSI_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator for ADC (HSI14) value. - */ -#if !defined (HSI14_VALUE) - #define HSI14_VALUE 14000000U /*!< Value of the Internal High Speed oscillator for ADC in Hz. - The real value may vary depending on the variations - in voltage and temperature. */ -#endif /* HSI14_VALUE */ - -/** - * @brief Internal High Speed oscillator for USB (HSI48) value. - */ -#if !defined (HSI48_VALUE) - #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB in Hz. - The real value may vary depending on the variations - in voltage and temperature. */ -#endif /* HSI48_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE 40000U -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -/** - * @brief Time out for LSE start up value in ms. - */ -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE 3300U /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0U -#define PREFETCH_ENABLE 1U -#define INSTRUCTION_CACHE_ENABLE 0U -#define DATA_CACHE_ENABLE 0U -#define USE_SPI_CRC 1U - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/*#define USE_FULL_ASSERT 1*/ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f0xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f0xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f0xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f0xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f0xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f0xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f0xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32f0xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f0xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f0xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f0xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f0xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f0xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f0xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f0xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f0xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f0xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f0xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f0xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32f0xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f0xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f0xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32f0xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f0xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f0xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f0xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0U : assert_failed((char *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(char* file, uint32_t line); -#else - #define assert_param(expr) ((void)0U) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F0xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F0XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h index daf9b63ceca01..de19251e0808a 100644 --- a/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F401RE/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h index 8f0b6638119d4..de19251e0808a 100644 --- a/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F411RE/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h index 5b5a8a3e43e52..de19251e0808a 100644 --- a/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F413ZH/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) - /* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F429ZI/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F429ZI/stm32f4xx_hal_conf.h index 5b5a8a3e43e52..de19251e0808a 100644 --- a/ports/stm32/boards/NUCLEO_F429ZI/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F429ZI/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) - /* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h index 245fb9a06ab6e..de19251e0808a 100644 --- a/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F446RE/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -/* #define HAL_RNG_MODULE_ENABLED */ -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F746ZG/stm32f7xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F746ZG/stm32f7xx_hal_conf.h index a019ee4ce9665..e241921ddd25b 100644 --- a/ports/stm32/boards/NUCLEO_F746ZG/stm32f7xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F746ZG/stm32f7xx_hal_conf.h @@ -1,427 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f7xx_hal_conf.h - * @author MCD Application Team - * @version V1.0.1 - * @date 25-June-2015 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F7xx_HAL_CONF_H -#define __STM32F7xx_HAL_CONF_H +#include "boards/stm32f7xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (5000) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CEC_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SPDIFRX_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## Timeout Configuration ######################### */ -/** - * @brief This is the HAL configuration section - */ -#define HAL_ACCURATE_TIMEOUT_ENABLED 0 -#define HAL_TIMEOUT_VALUE 0x1FFFFFF - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define ART_ACCLERATOR_ENABLE 1 /* To enable instruction cache and prefetch */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 1 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)5) /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)5) /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ -/* LAN8742A PHY Address*/ -#define LAN8742A_PHY_ADDRESS 0x00 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x00000FFF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f7xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f7xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f7xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f7xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f7xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f7xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f7xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f7xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f7xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f7xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f7xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f7xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f7xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f7xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f7xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f7xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f7xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f7xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f7xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f7xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED - #include "stm32f7xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f7xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f7xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32f7xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f7xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f7xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f7xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f7xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPDIFRX_MODULE_ENABLED - #include "stm32f7xx_hal_spdifrx.h" -#endif /* HAL_SPDIFRX_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f7xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f7xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f7xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f7xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f7xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f7xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f7xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f7xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f7xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F7xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_F767ZI/stm32f7xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F767ZI/stm32f7xx_hal_conf.h index a019ee4ce9665..e241921ddd25b 100644 --- a/ports/stm32/boards/NUCLEO_F767ZI/stm32f7xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_F767ZI/stm32f7xx_hal_conf.h @@ -1,427 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f7xx_hal_conf.h - * @author MCD Application Team - * @version V1.0.1 - * @date 25-June-2015 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F7xx_HAL_CONF_H -#define __STM32F7xx_HAL_CONF_H +#include "boards/stm32f7xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (5000) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CEC_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SPDIFRX_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## Timeout Configuration ######################### */ -/** - * @brief This is the HAL configuration section - */ -#define HAL_ACCURATE_TIMEOUT_ENABLED 0 -#define HAL_TIMEOUT_VALUE 0x1FFFFFF - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define ART_ACCLERATOR_ENABLE 1 /* To enable instruction cache and prefetch */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 1 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)5) /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)5) /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ -/* LAN8742A PHY Address*/ -#define LAN8742A_PHY_ADDRESS 0x00 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x00000FFF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f7xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f7xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f7xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f7xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f7xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f7xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f7xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f7xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f7xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f7xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f7xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f7xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f7xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f7xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f7xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f7xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f7xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f7xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f7xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f7xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED - #include "stm32f7xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f7xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f7xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32f7xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f7xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f7xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f7xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f7xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPDIFRX_MODULE_ENABLED - #include "stm32f7xx_hal_spdifrx.h" -#endif /* HAL_SPDIFRX_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f7xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f7xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f7xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f7xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f7xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f7xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f7xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f7xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f7xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F7xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_H743ZI/stm32h7xx_hal_conf.h b/ports/stm32/boards/NUCLEO_H743ZI/stm32h7xx_hal_conf.h index 97b141d49f8f3..45400cdcd734b 100644 --- a/ports/stm32/boards/NUCLEO_H743ZI/stm32h7xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_H743ZI/stm32h7xx_hal_conf.h @@ -1,434 +1,19 @@ -/** - ****************************************************************************** - * @file stm32h7xx_hal_conf_template.h - * @author MCD Application Team - * @version V1.2.0 - * @date 29-December-2017 - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32h7xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32H7xx_HAL_CONF_H -#define __STM32H7xx_HAL_CONF_H +#include "boards/stm32h7xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (5000) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CEC_MODULE_ENABLED -#define HAL_COMP_MODULE_ENABLED -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_CRC_MODULE_ENABLED -#define HAL_CRYP_MODULE_ENABLED -#define HAL_DAC_MODULE_ENABLED -#define HAL_DCMI_MODULE_ENABLED -#define HAL_DFSDM_MODULE_ENABLED -#define HAL_DMA_MODULE_ENABLED -#define HAL_DMA2D_MODULE_ENABLED -#define HAL_ETH_MODULE_ENABLED -#define HAL_FDCAN_MODULE_ENABLED -#define HAL_FLASH_MODULE_ENABLED -#define HAL_GPIO_MODULE_ENABLED -#define HAL_HASH_MODULE_ENABLED -#define HAL_HCD_MODULE_ENABLED -#define HAL_HRTIM_MODULE_ENABLED -#define HAL_HSEM_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -#define HAL_IRDA_MODULE_ENABLED -#define HAL_IWDG_MODULE_ENABLED -#define HAL_JPEG_MODULE_ENABLED -#define HAL_LPTIM_MODULE_ENABLED -#define HAL_LTDC_MODULE_ENABLED -#define HAL_MDIOS_MODULE_ENABLED -#define HAL_MDMA_MODULE_ENABLED -#define HAL_MMC_MODULE_ENABLED -#define HAL_NAND_MODULE_ENABLED -#define HAL_NOR_MODULE_ENABLED -#define HAL_OPAMP_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -#define HAL_QSPI_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -#define HAL_SAI_MODULE_ENABLED -#define HAL_SD_MODULE_ENABLED -#define HAL_SDRAM_MODULE_ENABLED -#define HAL_SMARTCARD_MODULE_ENABLED -#define HAL_SMBUS_MODULE_ENABLED -#define HAL_SPDIFRX_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_SRAM_MODULE_ENABLED -#define HAL_SWPMI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -#define HAL_USART_MODULE_ENABLED -#define HAL_WWDG_MODULE_ENABLED - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) -#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal oscillator (CSI) default value. - * This value is the default CSI value after Reset. - */ -#if !defined (CSI_VALUE) - #define CSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* CSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)64000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External clock in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define USE_SD_TRANSCEIVER 0U /*!< use uSD Transceiver */ - -/* ########################### Ethernet Configuration ######################### */ -#define ETH_TX_DESC_CNT 4 /* number of Ethernet Tx DMA descriptors */ -#define ETH_RX_DESC_CNT 4 /* number of Ethernet Rx DMA descriptors */ - -#define ETH_MAC_ADDR0 ((uint8_t)0x02) -#define ETH_MAC_ADDR1 ((uint8_t)0x00) -#define ETH_MAC_ADDR2 ((uint8_t)0x00) -#define ETH_MAC_ADDR3 ((uint8_t)0x00) -#define ETH_MAC_ADDR4 ((uint8_t)0x00) -#define ETH_MAC_ADDR5 ((uint8_t)0x00) - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## SPI peripheral configuration ########################## */ -/** - * @brief Used to activate CRC feature inside HAL SPI Driver - * Activated (1U): CRC code is compiled within HAL SPI driver - * Deactivated (0U): CRC code excluded from HAL SPI driver - */ - -#define USE_SPI_CRC 1U - - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32h7xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32h7xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32h7xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32h7xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32h7xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32h7xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32h7xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32h7xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32h7xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32h7xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_FDCAN_MODULE_ENABLED - #include "stm32h7xx_hal_fdcan.h" -#endif /* HAL_FDCAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32h7xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32h7xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32h7xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32h7xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32h7xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32h7xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_HRTIM_MODULE_ENABLED - #include "stm32h7xx_hal_hrtim.h" -#endif /* HAL_HRTIM_MODULE_ENABLED */ - -#ifdef HAL_HSEM_MODULE_ENABLED - #include "stm32h7xx_hal_hsem.h" -#endif /* HAL_HSEM_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32h7xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32h7xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32h7xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32h7xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32h7xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32h7xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_JPEG_MODULE_ENABLED - #include "stm32h7xx_hal_jpeg.h" -#endif /* HAL_JPEG_MODULE_ENABLED */ - -#ifdef HAL_MDIOS_MODULE_ENABLED - #include "stm32h7xx_hal_mdios.h" -#endif /* HAL_MDIOS_MODULE_ENABLED */ - -#ifdef HAL_MDMA_MODULE_ENABLED - #include "stm32h7xx_hal_mdma.h" -#endif /* HAL_MDMA_MODULE_ENABLED */ - -#ifdef HAL_MMC_MODULE_ENABLED - #include "stm32h7xx_hal_mmc.h" -#endif /* HAL_MMC_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32h7xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED -#include "stm32h7xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32h7xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32h7xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32h7xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32h7xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32h7xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32h7xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32h7xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32h7xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32h7xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SPDIFRX_MODULE_ENABLED - #include "stm32h7xx_hal_spdifrx.h" -#endif /* HAL_SPDIFRX_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32h7xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32h7xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32h7xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32h7xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32h7xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32h7xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32h7xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32h7xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32h7xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32h7xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32H7xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_L432KC/stm32l4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_L432KC/stm32l4xx_hal_conf.h index 1ee8fbabc4545..fd380ab7357e2 100755 --- a/ports/stm32/boards/NUCLEO_L432KC/stm32l4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_L432KC/stm32l4xx_hal_conf.h @@ -1,384 +1,20 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_conf.h - * @author MCD Application Team - * @version V1.2.0 - * @date 25-November-2015 - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32l4xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_COMP_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DFSDM_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_FIREWALL_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LCD_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_OPAMP_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -/* #define HAL_SD_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -/* #define HAL_SWPMI_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/* #define HAL_TSC_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ - - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal Multiple Speed oscillator (MSI) default value. - * This value is the default MSI range value after Reset. - */ -#if !defined (MSI_VALUE) - #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* MSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - - /** - * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. - * This internal oscillator is mainly dedicated to provide a high precision clock to - * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. - * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency - * which is subject to manufacturing process variations. - */ - #if !defined (HSI48_VALUE) - #define HSI48_VALUE ((uint32_t)48000000U) /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. - The real value my vary depending on manufacturing process variations.*/ - #endif /* HSI48_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/** - * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/ -#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32l4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32l4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32l4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32l4xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32l4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32l4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32l4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32l4xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32l4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32l4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32l4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FIREWALL_MODULE_ENABLED - #include "stm32l4xx_hal_firewall.h" -#endif /* HAL_FIREWALL_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32l4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32l4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32l4xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32L4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H + +#include "boards/stm32l4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) +#define EXTERNAL_SAI2_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H diff --git a/ports/stm32/boards/NUCLEO_L476RG/stm32l4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_L476RG/stm32l4xx_hal_conf.h index 6bfb28118a44b..fd380ab7357e2 100755 --- a/ports/stm32/boards/NUCLEO_L476RG/stm32l4xx_hal_conf.h +++ b/ports/stm32/boards/NUCLEO_L476RG/stm32l4xx_hal_conf.h @@ -1,372 +1,20 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_conf.h - * @author MCD Application Team - * @version V1.2.0 - * @date 25-November-2015 - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32l4xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_COMP_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DFSDM_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_FIREWALL_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LCD_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_OPAMP_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -/* #define HAL_SWPMI_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/* #define HAL_TSC_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ - - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal Multiple Speed oscillator (MSI) default value. - * This value is the default MSI range value after Reset. - */ -#if !defined (MSI_VALUE) - #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* MSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/** - * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/ -#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32l4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32l4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32l4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32l4xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32l4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32l4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32l4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32l4xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32l4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32l4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32l4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FIREWALL_MODULE_ENABLED - #include "stm32l4xx_hal_firewall.h" -#endif /* HAL_FIREWALL_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32l4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32l4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32l4xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32L4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H + +#include "boards/stm32l4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) +#define EXTERNAL_SAI2_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H diff --git a/ports/stm32/boards/OLIMEX_E407/stm32f4xx_hal_conf.h b/ports/stm32/boards/OLIMEX_E407/stm32f4xx_hal_conf.h index 24cc9228b80dd..9719157e55cdf 100644 --- a/ports/stm32/boards/OLIMEX_E407/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/OLIMEX_E407/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (12000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h b/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h index c820dafc44d72..621b05c719e92 100644 --- a/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h +++ b/ports/stm32/boards/PYBD_SF2/stm32f7xx_hal_conf.h @@ -1,74 +1,14 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * +/* This file is part of the MicroPython project, http://micropython.org/ * The MIT License (MIT) - * * Copyright (c) 2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. */ #ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H #define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H -// Include various HAL modules for convenience -#include "stm32f7xx_hal_dma.h" -#include "stm32f7xx_hal_adc.h" -#include "stm32f7xx_hal_can.h" -#include "stm32f7xx_hal_cortex.h" -#include "stm32f7xx_hal_dac.h" -#include "stm32f7xx_hal_flash.h" -#include "stm32f7xx_hal_gpio.h" -#include "stm32f7xx_hal_i2c.h" -#include "stm32f7xx_hal_mmc.h" -#include "stm32f7xx_hal_pcd.h" -#include "stm32f7xx_hal_pwr.h" -#include "stm32f7xx_hal_rcc.h" -#include "stm32f7xx_hal_rtc.h" -#include "stm32f7xx_hal_sd.h" -#include "stm32f7xx_hal_spi.h" -#include "stm32f7xx_hal_tim.h" -#include "stm32f7xx_hal_uart.h" - -// Enable various HAL modules -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_DAC_MODULE_ENABLED -#define HAL_DMA_MODULE_ENABLED -#define HAL_FLASH_MODULE_ENABLED -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_MMC_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED +#include "boards/stm32f7xx_hal_conf_base.h" // Oscillator values in Hz -#define HSI_VALUE (16000000) -#define HSE_VALUE ((uint32_t)25000000) -#define LSI_VALUE (32000) +#define HSE_VALUE (25000000) #define LSE_VALUE (32768) #define EXTERNAL_CLOCK_VALUE (12288000) @@ -76,13 +16,4 @@ #define HSE_STARTUP_TIMEOUT (5000) #define LSE_STARTUP_TIMEOUT (5000) -// SysTick has the highest priority -#define TICK_INT_PRIORITY (0x00) - -// No RTOS is used -#define USE_RTOS 0 - -// HAL parameter assertions are disabled -#define assert_param(expr) ((void)0) - #endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H diff --git a/ports/stm32/boards/PYBLITEV10/stm32f4xx_hal_conf.h b/ports/stm32/boards/PYBLITEV10/stm32f4xx_hal_conf.h index 4e96f785ad34b..9719157e55cdf 100644 --- a/ports/stm32/boards/PYBLITEV10/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/PYBLITEV10/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (12000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/PYBV10/stm32f4xx_hal_conf.h b/ports/stm32/boards/PYBV10/stm32f4xx_hal_conf.h index 4f18ac81e369e..de19251e0808a 100644 --- a/ports/stm32/boards/PYBV10/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/PYBV10/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/PYBV11/stm32f4xx_hal_conf.h b/ports/stm32/boards/PYBV11/stm32f4xx_hal_conf.h index 24cc9228b80dd..9719157e55cdf 100644 --- a/ports/stm32/boards/PYBV11/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/PYBV11/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (12000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/PYBV3/stm32f4xx_hal_conf.h b/ports/stm32/boards/PYBV3/stm32f4xx_hal_conf.h index daf9b63ceca01..de19251e0808a 100644 --- a/ports/stm32/boards/PYBV3/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/PYBV3/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/PYBV4/stm32f4xx_hal_conf.h b/ports/stm32/boards/PYBV4/stm32f4xx_hal_conf.h index daf9b63ceca01..de19251e0808a 100644 --- a/ports/stm32/boards/PYBV4/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/PYBV4/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32F411DISC/stm32f4xx_hal_conf.h b/ports/stm32/boards/STM32F411DISC/stm32f4xx_hal_conf.h index 8f0b6638119d4..de19251e0808a 100644 --- a/ports/stm32/boards/STM32F411DISC/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/STM32F411DISC/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32F429DISC/stm32f4xx_hal_conf.h b/ports/stm32/boards/STM32F429DISC/stm32f4xx_hal_conf.h index ec70793c8b915..de19251e0808a 100644 --- a/ports/stm32/boards/STM32F429DISC/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/STM32F429DISC/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) - /* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_SDRAM_MODULE_ENABLED -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32F439/stm32f4xx_hal_conf.h b/ports/stm32/boards/STM32F439/stm32f4xx_hal_conf.h index 5b5a8a3e43e52..de19251e0808a 100644 --- a/ports/stm32/boards/STM32F439/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/STM32F439/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) - /* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32F4DISC/stm32f4xx_hal_conf.h b/ports/stm32/boards/STM32F4DISC/stm32f4xx_hal_conf.h index daf9b63ceca01..de19251e0808a 100644 --- a/ports/stm32/boards/STM32F4DISC/stm32f4xx_hal_conf.h +++ b/ports/stm32/boards/STM32F4DISC/stm32f4xx_hal_conf.h @@ -1,409 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_conf.h - * @author MCD Application Team - * @version V1.1.0 - * @date 19-June-2014 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4xx_HAL_CONF_H -#define __STM32F4xx_HAL_CONF_H +#include "boards/stm32f4xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)40000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 0 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)4) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)4) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ - -/* DP83848 PHY Address*/ -#define DP83848_PHY_ADDRESS 0x01 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x000000FF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f4xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_PCCARD_MODULE_ENABLED - #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f4xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f4xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32F769DISC/stm32f7xx_hal_conf.h b/ports/stm32/boards/STM32F769DISC/stm32f7xx_hal_conf.h index 15933906720da..621b05c719e92 100644 --- a/ports/stm32/boards/STM32F769DISC/stm32f7xx_hal_conf.h +++ b/ports/stm32/boards/STM32F769DISC/stm32f7xx_hal_conf.h @@ -1,427 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f7xx_hal_conf.h - * @author MCD Application Team - * @version V1.0.1 - * @date 25-June-2015 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F7xx_HAL_CONF_H -#define __STM32F7xx_HAL_CONF_H +#include "boards/stm32f7xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (25000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (5000) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CEC_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -/* #define HAL_DAC_MODULE_ENABLED */ -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_SDRAM_MODULE_ENABLED -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SPDIFRX_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## Timeout Configuration ######################### */ -/** - * @brief This is the HAL configuration section - */ -#define HAL_ACCURATE_TIMEOUT_ENABLED 0 -#define HAL_TIMEOUT_VALUE 0x1FFFFFF - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define ART_ACCLERATOR_ENABLE 1 /* To enable instruction cache and prefetch */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 1 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)5) /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)5) /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ -/* LAN8742A PHY Address*/ -#define LAN8742A_PHY_ADDRESS 0x00 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x00000FFF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f7xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f7xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f7xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f7xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f7xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f7xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f7xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f7xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f7xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f7xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f7xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f7xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f7xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f7xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f7xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f7xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f7xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f7xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f7xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f7xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED - #include "stm32f7xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f7xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f7xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32f7xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f7xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f7xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f7xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f7xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPDIFRX_MODULE_ENABLED - #include "stm32f7xx_hal_spdifrx.h" -#endif /* HAL_SPDIFRX_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f7xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f7xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f7xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f7xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f7xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f7xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f7xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f7xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f7xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F7xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32F7DISC/stm32f7xx_hal_conf.h b/ports/stm32/boards/STM32F7DISC/stm32f7xx_hal_conf.h index 15933906720da..621b05c719e92 100644 --- a/ports/stm32/boards/STM32F7DISC/stm32f7xx_hal_conf.h +++ b/ports/stm32/boards/STM32F7DISC/stm32f7xx_hal_conf.h @@ -1,427 +1,19 @@ -/** - ****************************************************************************** - * @file stm32f7xx_hal_conf.h - * @author MCD Application Team - * @version V1.0.1 - * @date 25-June-2015 - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F7xx_HAL_CONF_H -#define __STM32F7xx_HAL_CONF_H +#include "boards/stm32f7xx_hal_conf_base.h" -#ifdef __cplusplus - extern "C" { -#endif +// Oscillator values in Hz +#define HSE_VALUE (25000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (5000) +#define LSE_STARTUP_TIMEOUT (5000) -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_CEC_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -/* #define HAL_DAC_MODULE_ENABLED */ -/* #define HAL_DCMI_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_SDRAM_MODULE_ENABLED -/* #define HAL_HASH_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_I2S_MODULE_ENABLED -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SPDIFRX_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ - - -/* ########################## Timeout Configuration ######################### */ -/** - * @brief This is the HAL configuration section - */ -#define HAL_ACCURATE_TIMEOUT_ENABLED 0 -#define HAL_TIMEOUT_VALUE 0x1FFFFFF - -/* ########################## HSE/HSI Values adaptation ##################### */ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ -#endif /* LSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. - */ -#if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* EXTERNAL_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define ART_ACCLERATOR_ENABLE 1 /* To enable instruction cache and prefetch */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* ################## Ethernet peripheral configuration ##################### */ - -/* Section 1 : Ethernet peripheral configuration */ - -/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ -#define MAC_ADDR0 2 -#define MAC_ADDR1 1 -#define MAC_ADDR2 0 -#define MAC_ADDR3 0 -#define MAC_ADDR4 0 -#define MAC_ADDR5 0 - -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB ((uint32_t)5) /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB ((uint32_t)5) /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ - -/* Section 2: PHY configuration section */ -/* LAN8742A PHY Address*/ -#define LAN8742A_PHY_ADDRESS 0x00 -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ -#define PHY_RESET_DELAY ((uint32_t)0x00000FFF) -/* PHY Configuration delay */ -#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFF) - -#define PHY_READ_TO ((uint32_t)0x0000FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0000FFFF) - -/* Section 3: Common PHY Registers */ - -#define PHY_BCR ((uint16_t)0x00) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x01) /*!< Transceiver Basic Status Register */ - -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ - -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ - -/* Section 4: Extended PHY Registers */ - -#define PHY_SR ((uint16_t)0x10) /*!< PHY status register Offset */ -#define PHY_MICR ((uint16_t)0x11) /*!< MII Interrupt Control Register */ -#define PHY_MISR ((uint16_t)0x12) /*!< MII Interrupt Status and Misc. Control Register */ - -#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ - -#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ -#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ - -#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ -#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32f7xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32f7xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32f7xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32f7xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32f7xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32f7xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_CEC_MODULE_ENABLED - #include "stm32f7xx_hal_cec.h" -#endif /* HAL_CEC_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32f7xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f7xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32f7xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32f7xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32f7xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_ETH_MODULE_ENABLED - #include "stm32f7xx_hal_eth.h" -#endif /* HAL_ETH_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32f7xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32f7xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32f7xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_SDRAM_MODULE_ENABLED - #include "stm32f7xx_hal_sdram.h" -#endif /* HAL_SDRAM_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32f7xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32f7xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_I2S_MODULE_ENABLED - #include "stm32f7xx_hal_i2s.h" -#endif /* HAL_I2S_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32f7xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED - #include "stm32f7xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32f7xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32f7xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32f7xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32f7xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32f7xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32f7xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32f7xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SPDIFRX_MODULE_ENABLED - #include "stm32f7xx_hal_spdifrx.h" -#endif /* HAL_SPDIFRX_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32f7xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32f7xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32f7xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32f7xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32f7xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32f7xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32f7xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32f7xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32f7xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F7xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32L476DISC/stm32l4xx_hal_conf.h b/ports/stm32/boards/STM32L476DISC/stm32l4xx_hal_conf.h index 6bfb28118a44b..fd380ab7357e2 100644 --- a/ports/stm32/boards/STM32L476DISC/stm32l4xx_hal_conf.h +++ b/ports/stm32/boards/STM32L476DISC/stm32l4xx_hal_conf.h @@ -1,372 +1,20 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_conf.h - * @author MCD Application Team - * @version V1.2.0 - * @date 25-November-2015 - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32l4xx_hal_conf.h. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2015 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_COMP_MODULE_ENABLED */ -#define HAL_CORTEX_MODULE_ENABLED -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DFSDM_MODULE_ENABLED */ -#define HAL_DMA_MODULE_ENABLED -/* #define HAL_FIREWALL_MODULE_ENABLED */ -#define HAL_FLASH_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LCD_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -/* #define HAL_OPAMP_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -/* #define HAL_QSPI_MODULE_ENABLED */ -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -/* #define HAL_SWPMI_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/* #define HAL_TSC_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ - - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal Multiple Speed oscillator (MSI) default value. - * This value is the default MSI range value after Reset. - */ -#if !defined (MSI_VALUE) - #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* MSI_VALUE */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/** - * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/ -#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32l4xx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32l4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32l4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32l4xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32l4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32l4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32l4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32l4xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32l4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32l4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32l4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_FIREWALL_MODULE_ENABLED - #include "stm32l4xx_hal_firewall.h" -#endif /* HAL_FIREWALL_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32l4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32l4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED -#include "stm32l4xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32L4xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H + +#include "boards/stm32l4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) +#define EXTERNAL_SAI2_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H diff --git a/ports/stm32/boards/STM32L496GDISC/stm32l4xx_hal_conf.h b/ports/stm32/boards/STM32L496GDISC/stm32l4xx_hal_conf.h index 884db5ef1a3de..fd380ab7357e2 100644 --- a/ports/stm32/boards/STM32L496GDISC/stm32l4xx_hal_conf.h +++ b/ports/stm32/boards/STM32L496GDISC/stm32l4xx_hal_conf.h @@ -1,421 +1,20 @@ -/** - ****************************************************************************** - * @file stm32l4xx_hal_conf.h - * @brief HAL configuration file. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2018 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32L4xx_HAL_CONF_H -#define __STM32L4xx_HAL_CONF_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ - -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -/*#define HAL_CRYP_MODULE_ENABLED */ -#define HAL_CAN_MODULE_ENABLED -/* #define HAL_COMP_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ -/* #define HAL_CRYP_MODULE_ENABLED */ -#define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -/*#define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_DFSDM_MODULE_ENABLED */ -/*#define HAL_DSI_MODULE_ENABLED */ -/*#define HAL_FIREWALL_MODULE_ENABLED */ -/*#define HAL_GFXMMU_MODULE_ENABLED */ -/*#define HAL_HCD_MODULE_ENABLED */ -/*#define HAL_HASH_MODULE_ENABLED */ -/*#define HAL_I2S_MODULE_ENABLED */ -/*#define HAL_IRDA_MODULE_ENABLED */ -/*#define HAL_IWDG_MODULE_ENABLED */ -/*#define HAL_LTDC_MODULE_ENABLED */ -/*#define HAL_LCD_MODULE_ENABLED */ -/*#define HAL_LPTIM_MODULE_ENABLED */ -/*#define HAL_NAND_MODULE_ENABLED */ -/*#define HAL_NOR_MODULE_ENABLED */ -/*#define HAL_OPAMP_MODULE_ENABLED */ -/*#define HAL_OSPI_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -/* #define HAL_SAI_MODULE_ENABLED */ -#define HAL_SD_MODULE_ENABLED -/* #define HAL_SMBUS_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -#define HAL_SPI_MODULE_ENABLED -/*#define HAL_SRAM_MODULE_ENABLED */ -/*#define HAL_SWPMI_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/*#define HAL_TSC_MODULE_ENABLED */ -#define HAL_UART_MODULE_ENABLED -/*#define HAL_USART_MODULE_ENABLED */ -/*#define HAL_WWDG_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_DMA_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_FLASH_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -#define HAL_CORTEX_MODULE_ENABLED - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) - #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT ((uint32_t)100) /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal Multiple Speed oscillator (MSI) default value. - * This value is the default MSI range value after Reset. - */ -#if !defined (MSI_VALUE) - #define MSI_VALUE ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* MSI_VALUE */ -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - - /** - * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. - * This internal oscillator is mainly dedicated to provide a high precision clock to - * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. - * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency - * which is subject to manufacturing process variations. - */ - #if !defined (HSI48_VALUE) - #define HSI48_VALUE ((uint32_t)48000000U) /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. - The real value my vary depending on manufacturing process variations.*/ - #endif /* HSI48_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) - #define LSI_VALUE ((uint32_t)32000) /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) - #define LSE_VALUE ((uint32_t)32768) /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT ((uint32_t)5000) /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) - #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/** - * @brief External clock source for SAI2 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) - #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)48000) /*!< Value of the SAI2 External clock source in Hz*/ -#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x00) /*!< tick interrupt priority */ -#define USE_RTOS 0 -#define PREFETCH_ENABLE 1 -#define INSTRUCTION_CACHE_ENABLE 1 -#define DATA_CACHE_ENABLE 1 - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1 */ - -/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver - * Activated: CRC code is present inside driver - * Deactivated: CRC code cleaned from driver +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H -#define USE_SPI_CRC 0 - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ - -#ifdef HAL_RCC_MODULE_ENABLED - #include "stm32l4xx_hal_rcc.h" - #include "stm32l4xx_hal_rcc_ex.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED - #include "stm32l4xx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_DMA_MODULE_ENABLED - #include "stm32l4xx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_DFSDM_MODULE_ENABLED - #include "stm32l4xx_hal_dfsdm.h" -#endif /* HAL_DFSDM_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED - #include "stm32l4xx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED - #include "stm32l4xx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_CAN_MODULE_ENABLED - #include "stm32l4xx_hal_can.h" -#endif /* HAL_CAN_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED - #include "stm32l4xx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED - #include "stm32l4xx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32l4xx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_DAC_MODULE_ENABLED - #include "stm32l4xx_hal_dac.h" -#endif /* HAL_DAC_MODULE_ENABLED */ - -#ifdef HAL_DCMI_MODULE_ENABLED - #include "stm32l4xx_hal_dcmi.h" -#endif /* HAL_DCMI_MODULE_ENABLED */ - -#ifdef HAL_DMA2D_MODULE_ENABLED - #include "stm32l4xx_hal_dma2d.h" -#endif /* HAL_DMA2D_MODULE_ENABLED */ - -#ifdef HAL_DSI_MODULE_ENABLED - #include "stm32l4xx_hal_dsi.h" -#endif /* HAL_DSI_MODULE_ENABLED */ - -#ifdef HAL_FIREWALL_MODULE_ENABLED - #include "stm32l4xx_hal_firewall.h" -#endif /* HAL_FIREWALL_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED - #include "stm32l4xx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED - #include "stm32l4xx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_SRAM_MODULE_ENABLED - #include "stm32l4xx_hal_sram.h" -#endif /* HAL_SRAM_MODULE_ENABLED */ - -#ifdef HAL_NOR_MODULE_ENABLED - #include "stm32l4xx_hal_nor.h" -#endif /* HAL_NOR_MODULE_ENABLED */ - -#ifdef HAL_NAND_MODULE_ENABLED - #include "stm32l4xx_hal_nand.h" -#endif /* HAL_NAND_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED - #include "stm32l4xx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED - #include "stm32l4xx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LCD_MODULE_ENABLED - #include "stm32l4xx_hal_lcd.h" -#endif /* HAL_LCD_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED - #include "stm32l4xx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_LTDC_MODULE_ENABLED - #include "stm32l4xx_hal_ltdc.h" -#endif /* HAL_LTDC_MODULE_ENABLED */ - -#ifdef HAL_OPAMP_MODULE_ENABLED - #include "stm32l4xx_hal_opamp.h" -#endif /* HAL_OPAMP_MODULE_ENABLED */ - -#ifdef HAL_OSPI_MODULE_ENABLED - #include "stm32l4xx_hal_ospi.h" -#endif /* HAL_OSPI_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED - #include "stm32l4xx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_QSPI_MODULE_ENABLED - #include "stm32l4xx_hal_qspi.h" -#endif /* HAL_QSPI_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED - #include "stm32l4xx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED - #include "stm32l4xx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED - #include "stm32l4xx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SD_MODULE_ENABLED - #include "stm32l4xx_hal_sd.h" -#endif /* HAL_SD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED - #include "stm32l4xx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED - #include "stm32l4xx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_SWPMI_MODULE_ENABLED - #include "stm32l4xx_hal_swpmi.h" -#endif /* HAL_SWPMI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED - #include "stm32l4xx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED - #include "stm32l4xx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED - #include "stm32l4xx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED - #include "stm32l4xx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED - #include "stm32l4xx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED - #include "stm32l4xx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED - #include "stm32l4xx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED - #include "stm32l4xx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED - #include "stm32l4xx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -#ifdef HAL_GFXMMU_MODULE_ENABLED - #include "stm32l4xx_hal_gfxmmu.h" -#endif /* HAL_GFXMMU_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ - #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ - void assert_failed(uint8_t* file, uint32_t line); -#else - #define assert_param(expr) ((void)0U) -#endif /* USE_FULL_ASSERT */ +#include "boards/stm32l4xx_hal_conf_base.h" -#ifdef __cplusplus -} -#endif +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) +#define EXTERNAL_SAI2_CLOCK_VALUE (48000) -#endif /* __STM32L4xx_HAL_CONF_H */ +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H From c60e0a09f0f9db84aee8fdf1de5f416a87cdf868 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 24 Jun 2019 12:05:17 +1000 Subject: [PATCH 0183/1299] travis: Selectively fetch git submodules only when needed. This saves time when building on Travis CI: unconditionally fetching all submodules takes about 40 seconds, but not all are needed for any given port, so only fetch as necessary. --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4ec5069050176..e16c36058c7c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,8 @@ cache: env: global: - MAKEOPTS="-j4" +git: + submodules: false # define the successive stages stages: @@ -30,6 +32,7 @@ jobs: - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: + - git submodule update --init lib/lwip lib/mbedtls lib/stm32lib - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 @@ -60,6 +63,7 @@ jobs: - gcc --version - python3 --version script: + - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix coverage @@ -80,6 +84,7 @@ jobs: - stage: test env: NAME="unix port build and tests" script: + - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix @@ -91,6 +96,7 @@ jobs: install: - sudo apt-get install gcc-multilib libffi-dev:i386 script: + - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix nanbox @@ -100,6 +106,7 @@ jobs: - stage: test env: NAME="unix stackless port build and tests" script: + - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1" @@ -122,6 +129,7 @@ jobs: - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: + - git submodule update --init lib/nrfx - make ${MAKEOPTS} -C ports/nrf # bare-arm and minimal ports From cc12f750b4020f65ef00b5de2ca3c5ab2627b9d6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 24 Jun 2019 12:52:34 +1000 Subject: [PATCH 0184/1299] travis: Build esp8266 firmware as part of Travis CI. Toolchain installation and build takes about 1 minute. --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.travis.yml b/.travis.yml index e16c36058c7c9..ff6b24b958b73 100644 --- a/.travis.yml +++ b/.travis.yml @@ -121,6 +121,18 @@ jobs: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- + # esp8266 port + - stage: test + env: NAME="esp8266 port build" + install: + - wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz + - zcat xtensa-lx106-elf-standalone.tar.gz | tar x + - export PATH=$(pwd)/xtensa-lx106-elf/bin:$PATH + script: + - git submodule update --init lib/axtls lib/berkeley-db-1.xx + - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/esp8266 + # nrf port - stage: test env: NAME="nrf port build" From e06dcad5d385369762f62aeccaff0ae3c6626acf Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 25 Jun 2019 11:18:36 +1000 Subject: [PATCH 0185/1299] travis: Build esp32 firmware as part of Travis CI. Toolchain installation and build takes about 3 minutes. --- .travis.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.travis.yml b/.travis.yml index ff6b24b958b73..b71cabcc808bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -121,6 +121,23 @@ jobs: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- + # esp32 port + - stage: test + env: NAME="esp32 port build" + install: + - sudo apt-get install python3-pip + - sudo pip3 install pyparsing + - wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz + - zcat xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz | tar x + - export PATH=$(pwd)/xtensa-esp32-elf/bin:$PATH + - git clone https://github.com/espressif/esp-idf.git + - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH :=" ports/esp32/Makefile | cut -d " " -f 3) + - git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 + script: + - git submodule update --init lib/berkeley-db-1.xx + - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/esp32 ESPIDF=$(pwd)/esp-idf + # esp8266 port - stage: test env: NAME="esp8266 port build" From 862cc45a9c3241101c5d89e18063724793f73e43 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Mon, 24 Jun 2019 14:11:56 +0200 Subject: [PATCH 0186/1299] py/mkrules.mk: Use $(CPP) not $(CC) -E for preprocessor rule. --- py/mkrules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 5c214090cc0c2..7690c54092501 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -53,7 +53,7 @@ vpath %.c . $(TOP) $(USER_C_MODULES) $(BUILD)/%.pp: %.c $(ECHO) "PreProcess $<" - $(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $< + $(Q)$(CPP) $(CFLAGS) -Wp,-C,-dD,-dI -o $@ $< # The following rule uses | to create an order only prerequisite. Order only # prerequisites only get built if they don't exist. They don't cause timestamp From 2f262d5f9a8a77ec611548162100d6df8e9703c0 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 25 Jun 2019 15:32:25 +1200 Subject: [PATCH 0187/1299] esp32/Makefile: Include all driver/*.c source files in the build. Fixes #4869. --- ports/esp32/Makefile | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 67e2f52415d3b..ec6d29695b13d 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -256,21 +256,7 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) ################################################################################ # List of object files from the ESP32 IDF components -ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\ - uart.o \ - periph_ctrl.o \ - ledc.o \ - gpio.o \ - timer.o \ - sdmmc_host.o \ - sdmmc_transaction.o \ - sdspi_crc.o \ - sdspi_host.o \ - sdspi_transaction.o \ - spi_master.o \ - spi_common.o \ - rtc_module.o \ - ) +ESPIDF_DRIVER_O = $(subst .c,.o,$(wildcard $(ESPCOMP)/driver/*.c)) ESPIDF_EFUSE_O = $(addprefix $(ESPCOMP)/efuse/,\ esp32/esp_efuse_table.o \ From d21d57864426d56fa13104e82568fe94dcf079ab Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 25 Jun 2019 15:43:54 +1000 Subject: [PATCH 0188/1299] stm32/usb: Fix regression with auto USB PID value giving PID=0xffff. Commit 9e68eec8eac1188eab0bc059560b877928783978 introduced a regression where the PID of the USB device would be 0xffff if the default value was used. This commit fixes that by using a signed int type. --- ports/stm32/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 2807d512bee17..69ba26c43864b 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -302,7 +302,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // note: PID=-1 means select PID based on mode // note: we support CDC as a synonym for VCP for backward compatibility uint16_t vid = args[ARG_vid].u_int; - uint16_t pid = args[ARG_pid].u_int; + mp_int_t pid = args[ARG_pid].u_int; uint8_t mode; if (strcmp(mode_str, "CDC+MSC") == 0 || strcmp(mode_str, "VCP+MSC") == 0) { if (pid == -1) { From d889def06b8cce97c8ef31c986e051f28cc6fbd7 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Fri, 3 May 2019 20:21:45 +0200 Subject: [PATCH 0189/1299] nrf/led: Adjust how board LEDs are defined. Change static LED functions to lowercase names, and trim down source code lines for variants of MICROPY_HW_LED_COUNT. Also rename configuration for MICROPY_HW_LEDx_LEVEL to MICROPY_HW_LEDx_PULLUP to align with global PULLUP configuration. --- .../boards/blueio_tag_evim/mpconfigboard.h | 5 +- ports/nrf/modules/board/led.c | 116 ++++++------------ 2 files changed, 36 insertions(+), 85 deletions(-) diff --git a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h index afc3f00a81fa7..2f1a106101052 100644 --- a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h +++ b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h @@ -46,13 +46,10 @@ #define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED1 (30) // LED1 -#define MICROPY_HW_LED1_LEVEL (0) +#define MICROPY_HW_LED1_PULLUP (0) #define MICROPY_HW_LED2 (20) // LED2 -#define MICROPY_HW_LED2_LEVEL (1) #define MICROPY_HW_LED3 (19) // LED3 -#define MICROPY_HW_LED3_LEVEL (1) #define MICROPY_HW_LED4 (18) // LED4 -#define MICROPY_HW_LED4_LEVEL (1) // UART config #define MICROPY_HW_UART1_RX (8) diff --git a/ports/nrf/modules/board/led.c b/ports/nrf/modules/board/led.c index 8b1eb560eadf4..5d7b54ecba78e 100644 --- a/ports/nrf/modules/board/led.c +++ b/ports/nrf/modules/board/led.c @@ -38,24 +38,24 @@ typedef struct _board_led_obj_t { mp_uint_t led_id; mp_uint_t hw_pin; uint8_t hw_pin_port; - bool act_level; + bool pullup; } board_led_obj_t; -static inline void LED_OFF(board_led_obj_t * const led_obj) { - if (led_obj->act_level) { - nrf_gpio_pin_clear(led_obj->hw_pin); +static inline void led_off(board_led_obj_t * const led_obj) { + if (led_obj->pullup) { + nrf_gpio_pin_set(led_obj->hw_pin); } else { - nrf_gpio_pin_set(led_obj->hw_pin); + nrf_gpio_pin_clear(led_obj->hw_pin); } } -static inline void LED_ON(board_led_obj_t * const led_obj) { - if (led_obj->act_level) { - nrf_gpio_pin_set(led_obj->hw_pin); +static inline void led_on(board_led_obj_t * const led_obj) { + if (led_obj->pullup) { + nrf_gpio_pin_clear(led_obj->hw_pin); } else { - nrf_gpio_pin_clear(led_obj->hw_pin); + nrf_gpio_pin_set(led_obj->hw_pin); } } @@ -64,89 +64,43 @@ static const board_led_obj_t board_led_obj[] = { #if MICROPY_HW_LED_TRICOLOR - {{&board_led_type}, BOARD_LED_RED, MICROPY_HW_LED_RED, 0, MICROPY_HW_LED_PULLUP != 0 ? 0 : 1}, - {{&board_led_type}, BOARD_LED_GREEN, MICROPY_HW_LED_GREEN,0, MICROPY_HW_LED_PULLUP != 0 ? 0 : 1}, - {{&board_led_type}, BOARD_LED_BLUE, MICROPY_HW_LED_BLUE,0, MICROPY_HW_LED_PULLUP != 0 ? 0 : 1}, - -#elif (MICROPY_HW_LED_COUNT == 1) - - {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, - #ifdef MICROPY_HW_LED1_LEVEL - MICROPY_HW_LED1_LEVEL, - #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 - #endif - }, - -#elif (MICROPY_HW_LED_COUNT == 2) - - {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, - #ifdef MICROPY_HW_LED1_LEVEL - MICROPY_HW_LED1_LEVEL, - #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 - #endif - }, - {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2, 0, - #ifdef MICROPY_HW_LED2_LEVEL - MICROPY_HW_LED2_LEVEL, - #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 - #endif - }, - -#elif (MICROPY_HW_LED_COUNT == 3) - - {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, - #ifdef MICROPY_HW_LED1_LEVEL - MICROPY_HW_LED1_LEVEL, - #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 - #endif - }, - {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2, 0, - #ifdef MICROPY_HW_LED2_LEVEL - MICROPY_HW_LED2_LEVEL, - #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 - #endif - }, - {{&board_led_type}, BOARD_LED3, MICROPY_HW_LED3, 0, - #ifdef MICROPY_HW_LED3_LEVEL - MICROPY_HW_LED3_LEVEL, - #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 - #endif - }, - -#else - + {{&board_led_type}, BOARD_LED_RED, MICROPY_HW_LED_RED, 0, MICROPY_HW_LED_PULLUP}, + {{&board_led_type}, BOARD_LED_GREEN, MICROPY_HW_LED_GREEN,0, MICROPY_HW_LED_PULLUP}, + {{&board_led_type}, BOARD_LED_BLUE, MICROPY_HW_LED_BLUE,0, MICROPY_HW_LED_PULLUP}, +#endif +#if (MICROPY_HW_LED_COUNT >= 1) {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, - #ifdef MICROPY_HW_LED1_LEVEL - MICROPY_HW_LED1_LEVEL, + #ifdef MICROPY_HW_LED1_PULLUP + MICROPY_HW_LED1_PULLUP #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + MICROPY_HW_LED_PULLUP #endif }, +#endif +#if (MICROPY_HW_LED_COUNT >= 2) {{&board_led_type}, BOARD_LED2, MICROPY_HW_LED2, 0, - #ifdef MICROPY_HW_LED2_LEVEL - MICROPY_HW_LED2_LEVEL, + #ifdef MICROPY_HW_LED2_PULLUP + MICROPY_HW_LED2_PULLUP #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + MICROPY_HW_LED_PULLUP #endif }, +#endif +#if (MICROPY_HW_LED_COUNT >= 3) {{&board_led_type}, BOARD_LED3, MICROPY_HW_LED3, 0, - #ifdef MICROPY_HW_LED3_LEVEL - MICROPY_HW_LED3_LEVEL, + #ifdef MICROPY_HW_LED3_PULLUP + MICROPY_HW_LED3_PULLUP #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + MICROPY_HW_LED_PULLUP #endif }, +#endif +#if (MICROPY_HW_LED_COUNT == 4) {{&board_led_type}, BOARD_LED4, MICROPY_HW_LED4, 0, - #ifdef MICROPY_HW_LED4_LEVEL - MICROPY_HW_LED4_LEVEL, + #ifdef MICROPY_HW_LED4_PULLUP + MICROPY_HW_LED4_PULLUP #else - MICROPY_HW_LED_PULLUP != 0 ? 0 : 1 + MICROPY_HW_LED_PULLUP #endif }, #endif @@ -156,17 +110,17 @@ static const board_led_obj_t board_led_obj[] = { void led_init(void) { for (uint8_t i = 0; i < NUM_LEDS; i++) { - LED_OFF((board_led_obj_t*)&board_led_obj[i]); + led_off((board_led_obj_t*)&board_led_obj[i]); nrf_gpio_cfg_output(board_led_obj[i].hw_pin); } } void led_state(board_led_obj_t * led_obj, int state) { if (state == 1) { - LED_ON(led_obj); + led_on(led_obj); } else { - LED_OFF(led_obj); + led_off(led_obj); } } From ced340d739e84737dd5c8e6b4ab9af2ea44e29e7 Mon Sep 17 00:00:00 2001 From: Mikhail Zakharov Date: Tue, 23 Apr 2019 11:06:11 -0400 Subject: [PATCH 0190/1299] unix/unix_mphal: Use CLOCK_MONOTONIC for ticks_ms/us when available. --- ports/unix/unix_mphal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index f27c62fd1d1dc..71edaa57acfbc 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -187,13 +187,25 @@ void mp_hal_stdout_tx_str(const char *str) { } mp_uint_t mp_hal_ticks_ms(void) { + #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) + struct timespec tv; + clock_gettime(CLOCK_MONOTONIC, &tv); + return tv.tv_sec * 1000 + tv.tv_nsec / 1000000; + #else struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000 + tv.tv_usec / 1000; + #endif } mp_uint_t mp_hal_ticks_us(void) { + #if (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) + struct timespec tv; + clock_gettime(CLOCK_MONOTONIC, &tv); + return tv.tv_sec * 1000000 + tv.tv_nsec / 1000; + #else struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec; + #endif } From b152bbddd132cf3f147a526efebedaf25eba29cd Mon Sep 17 00:00:00 2001 From: Jun Wu Date: Mon, 6 May 2019 00:31:11 -0700 Subject: [PATCH 0191/1299] py: Define EMIT_MACHINE_CODE as EMIT_NATIVE || EMIT_INLINE_ASM. The combination MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM is used in many places, so define a new macro for it. --- py/asmbase.c | 4 ++-- py/emitglue.c | 2 +- py/emitglue.h | 4 ++-- py/mpconfig.h | 3 +++ py/nativeglue.c | 2 +- tools/mpy-tool.py | 4 ++-- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/py/asmbase.c b/py/asmbase.c index 4c84c3b255d1d..ab861da1523ac 100644 --- a/py/asmbase.c +++ b/py/asmbase.c @@ -31,7 +31,7 @@ #include "py/misc.h" #include "py/asmbase.h" -#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM +#if MICROPY_EMIT_MACHINE_CODE void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels) { as->max_num_labels = max_num_labels; @@ -99,4 +99,4 @@ void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val) { } } -#endif // MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM +#endif // MICROPY_EMIT_MACHINE_CODE diff --git a/py/emitglue.c b/py/emitglue.c index c073258f01674..483a47025b122 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -88,7 +88,7 @@ void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, #endif } -#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM +#if MICROPY_EMIT_MACHINE_CODE void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, #if MICROPY_PERSISTENT_CODE_SAVE uint16_t prelude_offset, diff --git a/py/emitglue.h b/py/emitglue.h index 058f060186476..b67d49ed6d23a 100644 --- a/py/emitglue.h +++ b/py/emitglue.h @@ -63,13 +63,13 @@ typedef struct _mp_raw_code_t { size_t fun_data_len; uint16_t n_obj; uint16_t n_raw_code; - #if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM + #if MICROPY_EMIT_MACHINE_CODE uint16_t prelude_offset; uint16_t n_qstr; mp_qstr_link_entry_t *qstr_link; #endif #endif - #if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM + #if MICROPY_EMIT_MACHINE_CODE mp_uint_t type_sig; // for viper, compressed as 2-bit types; ret is MSB, then arg0, arg1, etc #endif } mp_raw_code_t; diff --git a/py/mpconfig.h b/py/mpconfig.h index 4172e175b243d..a111b27aec2e8 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -329,6 +329,9 @@ // Convenience definition for whether any inline assembler emitter is enabled #define MICROPY_EMIT_INLINE_ASM (MICROPY_EMIT_INLINE_THUMB || MICROPY_EMIT_INLINE_XTENSA) +// Convenience definition for whether any native or inline assembler emitter is enabled +#define MICROPY_EMIT_MACHINE_CODE (MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM) + /*****************************************************************************/ /* Compiler configuration */ diff --git a/py/nativeglue.c b/py/nativeglue.c index 11d7a283a272c..979265a870a45 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -77,7 +77,7 @@ mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type) { #endif -#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM +#if MICROPY_EMIT_MACHINE_CODE // convert a native value to a MicroPython object based on type mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) { diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index a97af7737f3c1..648d56fe057e9 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -410,13 +410,13 @@ def freeze_module(self, qstr_links=(), type_sig=0): print(' .fun_data_len = %u,' % len(self.bytecode)) print(' .n_obj = %u,' % len(self.objs)) print(' .n_raw_code = %u,' % len(self.raw_codes)) - print(' #if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM') + print(' #if MICROPY_EMIT_MACHINE_CODE') print(' .prelude_offset = %u,' % self.prelude_offset) print(' .n_qstr = %u,' % len(qstr_links)) print(' .qstr_link = NULL,') # TODO print(' #endif') print(' #endif') - print(' #if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM') + print(' #if MICROPY_EMIT_MACHINE_CODE') print(' .type_sig = %u,' % type_sig) print(' #endif') print('};') From d165a401dce66ba952b016d116b60e77b11f3e1f Mon Sep 17 00:00:00 2001 From: Jun Wu Date: Sun, 5 May 2019 23:14:25 -0700 Subject: [PATCH 0192/1299] py/persistentcode: Fix compilation with load and save both enabled. With both MICROPY_PERSISTENT_CODE_SAVE and MICROPY_PERSISTENT_CODE_LOAD enabled the code fails to compile, due to undeclared 'n_obj'. If MICROPY_EMIT_NATIVE is disabled there are more errors due to the use of undefined fields in mp_raw_code_t. This patch fixes such compilation by avoiding undefined fields. MICROPY_EMIT_NATIVE was changed to MICROPY_EMIT_MACHINE_CODE in this file to match the mp_raw_code_t definition. --- py/persistentcode.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index cc6e161f427e4..c1ca46f7e90e4 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -157,7 +157,7 @@ typedef struct _bytecode_prelude_t { uint code_info_size; } bytecode_prelude_t; -#if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_EMIT_NATIVE +#if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_EMIT_MACHINE_CODE // ip will point to start of opcodes // ip2 will point to simple_name, source_file qstrs @@ -183,7 +183,7 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_ #include "py/parsenum.h" -#if MICROPY_EMIT_NATIVE +#if MICROPY_EMIT_MACHINE_CODE #if MICROPY_EMIT_THUMB STATIC void asm_thumb_rewrite_mov(uint8_t *pc, uint16_t val) { @@ -327,7 +327,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { int kind = (kind_len & 3) + MP_CODE_BYTECODE; size_t fun_data_len = kind_len >> 2; - #if !MICROPY_EMIT_NATIVE + #if !MICROPY_EMIT_MACHINE_CODE if (kind != MP_CODE_BYTECODE) { mp_raise_ValueError("incompatible .mpy file"); } @@ -336,7 +336,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { uint8_t *fun_data = NULL; byte *ip2; bytecode_prelude_t prelude = {0}; - #if MICROPY_EMIT_NATIVE + #if MICROPY_EMIT_MACHINE_CODE size_t prelude_offset; mp_uint_t type_sig = 0; size_t n_qstr_link = 0; @@ -353,7 +353,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { // Load bytecode load_bytecode(reader, qw, ip, fun_data + fun_data_len); - #if MICROPY_EMIT_NATIVE + #if MICROPY_EMIT_MACHINE_CODE } else { // Allocate memory for native data and load it size_t fun_alloc; @@ -404,13 +404,16 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { ip2[2] = source_file; ip2[3] = source_file >> 8; } + size_t n_obj = 0; + size_t n_raw_code = 0; mp_uint_t *const_table = NULL; + if (kind != MP_CODE_NATIVE_ASM) { // Load constant table for bytecode, native and viper // Number of entries in constant table - size_t n_obj = read_uint(reader, NULL); - size_t n_raw_code = read_uint(reader, NULL); + n_obj = read_uint(reader, NULL); + n_raw_code = read_uint(reader, NULL); // Allocate constant table size_t n_alloc = prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code; @@ -426,7 +429,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { *ct++ = (mp_uint_t)MP_OBJ_NEW_QSTR(load_qstr(reader, qw)); } - #if MICROPY_EMIT_NATIVE + #if MICROPY_EMIT_MACHINE_CODE if (kind != MP_CODE_BYTECODE) { // Populate mp_fun_table entry *ct++ = (mp_uint_t)(uintptr_t)mp_fun_table; @@ -455,7 +458,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { #endif prelude.scope_flags); - #if MICROPY_EMIT_NATIVE + #if MICROPY_EMIT_MACHINE_CODE } else { #if defined(MP_PLAT_COMMIT_EXEC) fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len); @@ -626,6 +629,7 @@ STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *q // Save bytecode save_bytecode(print, qstr_window, ip, ip_top); + #if MICROPY_EMIT_MACHINE_CODE } else { // Save native code mp_print_bytes(print, rc->fun_data, rc->fun_data_len); @@ -654,6 +658,7 @@ STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *q mp_print_uint(print, rc->type_sig); } } + #endif } if (rc->kind == MP_CODE_BYTECODE || rc->kind == MP_CODE_NATIVE_PY) { From d86fb670e6d78ca38dbaedfdde35180e3b8f4bb3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 18 Jun 2019 23:44:16 +1000 Subject: [PATCH 0193/1299] tests: Rename "bench" tests to "internal_bench" and run-internalbench.py To emphasise these benchmark tests compare the internal performance of features amongst themselves, rather than absolute performance testing. --- tests/{bench => internal_bench}/arrayop-1-list_inplace.py | 0 tests/{bench => internal_bench}/arrayop-2-list_map.py | 0 tests/{bench => internal_bench}/arrayop-3-bytearray_inplace.py | 0 tests/{bench => internal_bench}/arrayop-4-bytearray_map.py | 0 tests/{bench => internal_bench}/bench.py | 0 tests/{bench => internal_bench}/bytealloc-1-bytes_n.py | 0 tests/{bench => internal_bench}/bytealloc-2-repeat.py | 0 tests/{bench => internal_bench}/bytebuf-1-inplace.py | 0 tests/{bench => internal_bench}/bytebuf-2-join_map_bytes.py | 0 tests/{bench => internal_bench}/bytebuf-3-bytarray_map.py | 0 tests/{bench => internal_bench}/from_iter-1-list_bound.py | 0 tests/{bench => internal_bench}/from_iter-2-list_unbound.py | 0 tests/{bench => internal_bench}/from_iter-3-tuple_bound.py | 0 tests/{bench => internal_bench}/from_iter-4-tuple_unbound.py | 0 tests/{bench => internal_bench}/from_iter-5-bytes_bound.py | 0 tests/{bench => internal_bench}/from_iter-6-bytes_unbound.py | 0 tests/{bench => internal_bench}/from_iter-7-bytearray_bound.py | 0 .../{bench => internal_bench}/from_iter-8-bytearray_unbound.py | 0 tests/{bench => internal_bench}/func_args-1.1-pos_1.py | 0 tests/{bench => internal_bench}/func_args-1.2-pos_3.py | 0 .../{bench => internal_bench}/func_args-2-pos_default_2_of_3.py | 0 tests/{bench => internal_bench}/func_args-3.1-kw_1.py | 0 tests/{bench => internal_bench}/func_args-3.2-kw_3.py | 0 tests/{bench => internal_bench}/func_builtin-1-enum_pos.py | 0 tests/{bench => internal_bench}/func_builtin-2-enum_kw.py | 0 tests/{bench => internal_bench}/funcall-1-inline.py | 0 tests/{bench => internal_bench}/funcall-2-funcall.py | 0 tests/{bench => internal_bench}/funcall-3-funcall-local.py | 0 tests/{bench => internal_bench}/loop_count-1-range.py | 0 tests/{bench => internal_bench}/loop_count-2-range_iter.py | 0 tests/{bench => internal_bench}/loop_count-3-while_up.py | 0 tests/{bench => internal_bench}/loop_count-4-while_down_gt.py | 0 tests/{bench => internal_bench}/loop_count-5-while_down_ne.py | 0 .../loop_count-5.1-while_down_ne_localvar.py | 0 tests/{bench => internal_bench}/var-1-constant.py | 0 tests/{bench => internal_bench}/var-2-global.py | 0 tests/{bench => internal_bench}/var-3-local.py | 0 tests/{bench => internal_bench}/var-4-arg.py | 0 tests/{bench => internal_bench}/var-5-class-attr.py | 0 tests/{bench => internal_bench}/var-6-instance-attr.py | 0 tests/{bench => internal_bench}/var-6.1-instance-attr-5.py | 0 tests/{bench => internal_bench}/var-7-instance-meth.py | 0 tests/{bench => internal_bench}/var-8-namedtuple-1st.py | 0 tests/{bench => internal_bench}/var-8.1-namedtuple-5th.py | 0 tests/{run-bench-tests => run-internalbench.py} | 2 +- 45 files changed, 1 insertion(+), 1 deletion(-) rename tests/{bench => internal_bench}/arrayop-1-list_inplace.py (100%) rename tests/{bench => internal_bench}/arrayop-2-list_map.py (100%) rename tests/{bench => internal_bench}/arrayop-3-bytearray_inplace.py (100%) rename tests/{bench => internal_bench}/arrayop-4-bytearray_map.py (100%) rename tests/{bench => internal_bench}/bench.py (100%) rename tests/{bench => internal_bench}/bytealloc-1-bytes_n.py (100%) rename tests/{bench => internal_bench}/bytealloc-2-repeat.py (100%) rename tests/{bench => internal_bench}/bytebuf-1-inplace.py (100%) rename tests/{bench => internal_bench}/bytebuf-2-join_map_bytes.py (100%) rename tests/{bench => internal_bench}/bytebuf-3-bytarray_map.py (100%) rename tests/{bench => internal_bench}/from_iter-1-list_bound.py (100%) rename tests/{bench => internal_bench}/from_iter-2-list_unbound.py (100%) rename tests/{bench => internal_bench}/from_iter-3-tuple_bound.py (100%) rename tests/{bench => internal_bench}/from_iter-4-tuple_unbound.py (100%) rename tests/{bench => internal_bench}/from_iter-5-bytes_bound.py (100%) rename tests/{bench => internal_bench}/from_iter-6-bytes_unbound.py (100%) rename tests/{bench => internal_bench}/from_iter-7-bytearray_bound.py (100%) rename tests/{bench => internal_bench}/from_iter-8-bytearray_unbound.py (100%) rename tests/{bench => internal_bench}/func_args-1.1-pos_1.py (100%) rename tests/{bench => internal_bench}/func_args-1.2-pos_3.py (100%) rename tests/{bench => internal_bench}/func_args-2-pos_default_2_of_3.py (100%) rename tests/{bench => internal_bench}/func_args-3.1-kw_1.py (100%) rename tests/{bench => internal_bench}/func_args-3.2-kw_3.py (100%) rename tests/{bench => internal_bench}/func_builtin-1-enum_pos.py (100%) rename tests/{bench => internal_bench}/func_builtin-2-enum_kw.py (100%) rename tests/{bench => internal_bench}/funcall-1-inline.py (100%) rename tests/{bench => internal_bench}/funcall-2-funcall.py (100%) rename tests/{bench => internal_bench}/funcall-3-funcall-local.py (100%) rename tests/{bench => internal_bench}/loop_count-1-range.py (100%) rename tests/{bench => internal_bench}/loop_count-2-range_iter.py (100%) rename tests/{bench => internal_bench}/loop_count-3-while_up.py (100%) rename tests/{bench => internal_bench}/loop_count-4-while_down_gt.py (100%) rename tests/{bench => internal_bench}/loop_count-5-while_down_ne.py (100%) rename tests/{bench => internal_bench}/loop_count-5.1-while_down_ne_localvar.py (100%) rename tests/{bench => internal_bench}/var-1-constant.py (100%) rename tests/{bench => internal_bench}/var-2-global.py (100%) rename tests/{bench => internal_bench}/var-3-local.py (100%) rename tests/{bench => internal_bench}/var-4-arg.py (100%) rename tests/{bench => internal_bench}/var-5-class-attr.py (100%) rename tests/{bench => internal_bench}/var-6-instance-attr.py (100%) rename tests/{bench => internal_bench}/var-6.1-instance-attr-5.py (100%) rename tests/{bench => internal_bench}/var-7-instance-meth.py (100%) rename tests/{bench => internal_bench}/var-8-namedtuple-1st.py (100%) rename tests/{bench => internal_bench}/var-8.1-namedtuple-5th.py (100%) rename tests/{run-bench-tests => run-internalbench.py} (98%) diff --git a/tests/bench/arrayop-1-list_inplace.py b/tests/internal_bench/arrayop-1-list_inplace.py similarity index 100% rename from tests/bench/arrayop-1-list_inplace.py rename to tests/internal_bench/arrayop-1-list_inplace.py diff --git a/tests/bench/arrayop-2-list_map.py b/tests/internal_bench/arrayop-2-list_map.py similarity index 100% rename from tests/bench/arrayop-2-list_map.py rename to tests/internal_bench/arrayop-2-list_map.py diff --git a/tests/bench/arrayop-3-bytearray_inplace.py b/tests/internal_bench/arrayop-3-bytearray_inplace.py similarity index 100% rename from tests/bench/arrayop-3-bytearray_inplace.py rename to tests/internal_bench/arrayop-3-bytearray_inplace.py diff --git a/tests/bench/arrayop-4-bytearray_map.py b/tests/internal_bench/arrayop-4-bytearray_map.py similarity index 100% rename from tests/bench/arrayop-4-bytearray_map.py rename to tests/internal_bench/arrayop-4-bytearray_map.py diff --git a/tests/bench/bench.py b/tests/internal_bench/bench.py similarity index 100% rename from tests/bench/bench.py rename to tests/internal_bench/bench.py diff --git a/tests/bench/bytealloc-1-bytes_n.py b/tests/internal_bench/bytealloc-1-bytes_n.py similarity index 100% rename from tests/bench/bytealloc-1-bytes_n.py rename to tests/internal_bench/bytealloc-1-bytes_n.py diff --git a/tests/bench/bytealloc-2-repeat.py b/tests/internal_bench/bytealloc-2-repeat.py similarity index 100% rename from tests/bench/bytealloc-2-repeat.py rename to tests/internal_bench/bytealloc-2-repeat.py diff --git a/tests/bench/bytebuf-1-inplace.py b/tests/internal_bench/bytebuf-1-inplace.py similarity index 100% rename from tests/bench/bytebuf-1-inplace.py rename to tests/internal_bench/bytebuf-1-inplace.py diff --git a/tests/bench/bytebuf-2-join_map_bytes.py b/tests/internal_bench/bytebuf-2-join_map_bytes.py similarity index 100% rename from tests/bench/bytebuf-2-join_map_bytes.py rename to tests/internal_bench/bytebuf-2-join_map_bytes.py diff --git a/tests/bench/bytebuf-3-bytarray_map.py b/tests/internal_bench/bytebuf-3-bytarray_map.py similarity index 100% rename from tests/bench/bytebuf-3-bytarray_map.py rename to tests/internal_bench/bytebuf-3-bytarray_map.py diff --git a/tests/bench/from_iter-1-list_bound.py b/tests/internal_bench/from_iter-1-list_bound.py similarity index 100% rename from tests/bench/from_iter-1-list_bound.py rename to tests/internal_bench/from_iter-1-list_bound.py diff --git a/tests/bench/from_iter-2-list_unbound.py b/tests/internal_bench/from_iter-2-list_unbound.py similarity index 100% rename from tests/bench/from_iter-2-list_unbound.py rename to tests/internal_bench/from_iter-2-list_unbound.py diff --git a/tests/bench/from_iter-3-tuple_bound.py b/tests/internal_bench/from_iter-3-tuple_bound.py similarity index 100% rename from tests/bench/from_iter-3-tuple_bound.py rename to tests/internal_bench/from_iter-3-tuple_bound.py diff --git a/tests/bench/from_iter-4-tuple_unbound.py b/tests/internal_bench/from_iter-4-tuple_unbound.py similarity index 100% rename from tests/bench/from_iter-4-tuple_unbound.py rename to tests/internal_bench/from_iter-4-tuple_unbound.py diff --git a/tests/bench/from_iter-5-bytes_bound.py b/tests/internal_bench/from_iter-5-bytes_bound.py similarity index 100% rename from tests/bench/from_iter-5-bytes_bound.py rename to tests/internal_bench/from_iter-5-bytes_bound.py diff --git a/tests/bench/from_iter-6-bytes_unbound.py b/tests/internal_bench/from_iter-6-bytes_unbound.py similarity index 100% rename from tests/bench/from_iter-6-bytes_unbound.py rename to tests/internal_bench/from_iter-6-bytes_unbound.py diff --git a/tests/bench/from_iter-7-bytearray_bound.py b/tests/internal_bench/from_iter-7-bytearray_bound.py similarity index 100% rename from tests/bench/from_iter-7-bytearray_bound.py rename to tests/internal_bench/from_iter-7-bytearray_bound.py diff --git a/tests/bench/from_iter-8-bytearray_unbound.py b/tests/internal_bench/from_iter-8-bytearray_unbound.py similarity index 100% rename from tests/bench/from_iter-8-bytearray_unbound.py rename to tests/internal_bench/from_iter-8-bytearray_unbound.py diff --git a/tests/bench/func_args-1.1-pos_1.py b/tests/internal_bench/func_args-1.1-pos_1.py similarity index 100% rename from tests/bench/func_args-1.1-pos_1.py rename to tests/internal_bench/func_args-1.1-pos_1.py diff --git a/tests/bench/func_args-1.2-pos_3.py b/tests/internal_bench/func_args-1.2-pos_3.py similarity index 100% rename from tests/bench/func_args-1.2-pos_3.py rename to tests/internal_bench/func_args-1.2-pos_3.py diff --git a/tests/bench/func_args-2-pos_default_2_of_3.py b/tests/internal_bench/func_args-2-pos_default_2_of_3.py similarity index 100% rename from tests/bench/func_args-2-pos_default_2_of_3.py rename to tests/internal_bench/func_args-2-pos_default_2_of_3.py diff --git a/tests/bench/func_args-3.1-kw_1.py b/tests/internal_bench/func_args-3.1-kw_1.py similarity index 100% rename from tests/bench/func_args-3.1-kw_1.py rename to tests/internal_bench/func_args-3.1-kw_1.py diff --git a/tests/bench/func_args-3.2-kw_3.py b/tests/internal_bench/func_args-3.2-kw_3.py similarity index 100% rename from tests/bench/func_args-3.2-kw_3.py rename to tests/internal_bench/func_args-3.2-kw_3.py diff --git a/tests/bench/func_builtin-1-enum_pos.py b/tests/internal_bench/func_builtin-1-enum_pos.py similarity index 100% rename from tests/bench/func_builtin-1-enum_pos.py rename to tests/internal_bench/func_builtin-1-enum_pos.py diff --git a/tests/bench/func_builtin-2-enum_kw.py b/tests/internal_bench/func_builtin-2-enum_kw.py similarity index 100% rename from tests/bench/func_builtin-2-enum_kw.py rename to tests/internal_bench/func_builtin-2-enum_kw.py diff --git a/tests/bench/funcall-1-inline.py b/tests/internal_bench/funcall-1-inline.py similarity index 100% rename from tests/bench/funcall-1-inline.py rename to tests/internal_bench/funcall-1-inline.py diff --git a/tests/bench/funcall-2-funcall.py b/tests/internal_bench/funcall-2-funcall.py similarity index 100% rename from tests/bench/funcall-2-funcall.py rename to tests/internal_bench/funcall-2-funcall.py diff --git a/tests/bench/funcall-3-funcall-local.py b/tests/internal_bench/funcall-3-funcall-local.py similarity index 100% rename from tests/bench/funcall-3-funcall-local.py rename to tests/internal_bench/funcall-3-funcall-local.py diff --git a/tests/bench/loop_count-1-range.py b/tests/internal_bench/loop_count-1-range.py similarity index 100% rename from tests/bench/loop_count-1-range.py rename to tests/internal_bench/loop_count-1-range.py diff --git a/tests/bench/loop_count-2-range_iter.py b/tests/internal_bench/loop_count-2-range_iter.py similarity index 100% rename from tests/bench/loop_count-2-range_iter.py rename to tests/internal_bench/loop_count-2-range_iter.py diff --git a/tests/bench/loop_count-3-while_up.py b/tests/internal_bench/loop_count-3-while_up.py similarity index 100% rename from tests/bench/loop_count-3-while_up.py rename to tests/internal_bench/loop_count-3-while_up.py diff --git a/tests/bench/loop_count-4-while_down_gt.py b/tests/internal_bench/loop_count-4-while_down_gt.py similarity index 100% rename from tests/bench/loop_count-4-while_down_gt.py rename to tests/internal_bench/loop_count-4-while_down_gt.py diff --git a/tests/bench/loop_count-5-while_down_ne.py b/tests/internal_bench/loop_count-5-while_down_ne.py similarity index 100% rename from tests/bench/loop_count-5-while_down_ne.py rename to tests/internal_bench/loop_count-5-while_down_ne.py diff --git a/tests/bench/loop_count-5.1-while_down_ne_localvar.py b/tests/internal_bench/loop_count-5.1-while_down_ne_localvar.py similarity index 100% rename from tests/bench/loop_count-5.1-while_down_ne_localvar.py rename to tests/internal_bench/loop_count-5.1-while_down_ne_localvar.py diff --git a/tests/bench/var-1-constant.py b/tests/internal_bench/var-1-constant.py similarity index 100% rename from tests/bench/var-1-constant.py rename to tests/internal_bench/var-1-constant.py diff --git a/tests/bench/var-2-global.py b/tests/internal_bench/var-2-global.py similarity index 100% rename from tests/bench/var-2-global.py rename to tests/internal_bench/var-2-global.py diff --git a/tests/bench/var-3-local.py b/tests/internal_bench/var-3-local.py similarity index 100% rename from tests/bench/var-3-local.py rename to tests/internal_bench/var-3-local.py diff --git a/tests/bench/var-4-arg.py b/tests/internal_bench/var-4-arg.py similarity index 100% rename from tests/bench/var-4-arg.py rename to tests/internal_bench/var-4-arg.py diff --git a/tests/bench/var-5-class-attr.py b/tests/internal_bench/var-5-class-attr.py similarity index 100% rename from tests/bench/var-5-class-attr.py rename to tests/internal_bench/var-5-class-attr.py diff --git a/tests/bench/var-6-instance-attr.py b/tests/internal_bench/var-6-instance-attr.py similarity index 100% rename from tests/bench/var-6-instance-attr.py rename to tests/internal_bench/var-6-instance-attr.py diff --git a/tests/bench/var-6.1-instance-attr-5.py b/tests/internal_bench/var-6.1-instance-attr-5.py similarity index 100% rename from tests/bench/var-6.1-instance-attr-5.py rename to tests/internal_bench/var-6.1-instance-attr-5.py diff --git a/tests/bench/var-7-instance-meth.py b/tests/internal_bench/var-7-instance-meth.py similarity index 100% rename from tests/bench/var-7-instance-meth.py rename to tests/internal_bench/var-7-instance-meth.py diff --git a/tests/bench/var-8-namedtuple-1st.py b/tests/internal_bench/var-8-namedtuple-1st.py similarity index 100% rename from tests/bench/var-8-namedtuple-1st.py rename to tests/internal_bench/var-8-namedtuple-1st.py diff --git a/tests/bench/var-8.1-namedtuple-5th.py b/tests/internal_bench/var-8.1-namedtuple-5th.py similarity index 100% rename from tests/bench/var-8.1-namedtuple-5th.py rename to tests/internal_bench/var-8.1-namedtuple-5th.py diff --git a/tests/run-bench-tests b/tests/run-internalbench.py similarity index 98% rename from tests/run-bench-tests rename to tests/run-internalbench.py index f4a6776cbc29a..f6294572f0091 100755 --- a/tests/run-bench-tests +++ b/tests/run-internalbench.py @@ -74,7 +74,7 @@ def main(): if len(args.files) == 0: if pyb is None: # run PC tests - test_dirs = ('bench',) + test_dirs = ('internal_bench',) else: # run pyboard tests test_dirs = ('basics', 'float', 'pyb') From e92c9aa9c94eae7971c8e82f4e875fc53ef52f07 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 26 Jun 2019 14:23:03 +1000 Subject: [PATCH 0194/1299] tests: Add performance benchmarking test-suite framework. This benchmarking test suite is intended to be run on any MicroPython target. As such all tests are parameterised with N and M: N is the approximate CPU frequency (in MHz) of the target and M is the approximate amount of heap memory (in kbytes) available on the target. When running the benchmark suite these parameters must be specified and then each test is tuned to run on that target in a reasonable time (<1 second). The test scripts are not standalone: they require adding some extra code at the end to run the test with the appropriate parameters. This is done automatically by the run-perfbench.py script, in such a way that imports are minimised (so the tests can be run on targets without filesystem support). To interface with the benchmarking framework, each test provides a bm_params dict and a bm_setup function, with the later taking a set of parameters (chosen based on N, M) and returning a pair of functions, one to run the test and one to get the results. When running the test the number of microseconds taken by the test are recorded. Then this is converted into a benchmark score by inverting it (so higher number is faster) and normalising it with an appropriate factor (based roughly on the amount of work done by the test, eg number of iterations). Test outputs are also compared against a "truth" value, computed by running the test with CPython. This provides a basic way of making sure the test actually ran correctly. Each test is run multiple times and the results averaged and standard deviation computed. This is output as a summary of the test. To make comparisons of performance across different runs the run-perfbench.py script also includes a diff mode that reads in the output of two previous runs and computes the difference in performance. Reports are given as a percentage change in performance with a combined standard deviation to give an indication if the noise in the benchmarking is less than the thing that is being measured. Example invocations for PC, pyboard and esp8266 targets respectively: $ ./run-perfbench.py 1000 1000 $ ./run-perfbench.py --pyboard 100 100 $ ./run-perfbench.py --pyboard --device /dev/ttyUSB0 50 25 --- tests/perf_bench/benchrun.py | 26 ++++ tests/run-perfbench.py | 241 +++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 tests/perf_bench/benchrun.py create mode 100755 tests/run-perfbench.py diff --git a/tests/perf_bench/benchrun.py b/tests/perf_bench/benchrun.py new file mode 100644 index 0000000000000..9cbc9695aca7b --- /dev/null +++ b/tests/perf_bench/benchrun.py @@ -0,0 +1,26 @@ +def bm_run(N, M): + try: + from utime import ticks_us, ticks_diff + except ImportError: + import time + ticks_us = lambda: int(time.perf_counter() * 1000000) + ticks_diff = lambda a, b: a - b + + # Pick sensible parameters given N, M + cur_nm = (0, 0) + param = None + for nm, p in bm_params.items(): + if 10 * nm[0] <= 12 * N and nm[1] <= M and nm > cur_nm: + cur_nm = nm + param = p + if param is None: + print(-1, -1, 'no matching params') + return + + # Run and time benchmark + run, result = bm_setup(param) + t0 = ticks_us() + run() + t1 = ticks_us() + norm, out = result() + print(ticks_diff(t1, t0), norm, out) diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py new file mode 100755 index 0000000000000..d8100ef81d194 --- /dev/null +++ b/tests/run-perfbench.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python3 + +# This file is part of the MicroPython project, http://micropython.org/ +# The MIT License (MIT) +# Copyright (c) 2019 Damien P. George + +import os +import subprocess +import sys +import argparse +from glob import glob + +sys.path.append('../tools') +import pyboard + +# Paths for host executables +if os.name == 'nt': + CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe') + MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/windows/micropython.exe') +else: + CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') + MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython') + +PYTHON_TRUTH = CPYTHON3 + +BENCH_SCRIPT_DIR = 'perf_bench/' + +def compute_stats(lst): + avg = 0 + var = 0 + for x in lst: + avg += x + var += x * x + avg /= len(lst) + var = max(0, var / len(lst) - avg ** 2) + return avg, var ** 0.5 + +def run_script_on_target(target, script): + output = b'' + err = None + + if isinstance(target, pyboard.Pyboard): + # Run via pyboard interface + try: + target.enter_raw_repl() + output = target.exec_(script) + except pyboard.PyboardError as er: + err = er + else: + # Run local executable + try: + p = subprocess.run([target], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, input=script) + output = p.stdout + except subprocess.CalledProcessError as er: + err = er + + return str(output.strip(), 'ascii'), err + +def run_feature_test(target, test): + with open('feature_check/' + test + '.py', 'rb') as f: + script = f.read() + output, err = run_script_on_target(target, script) + if err is None: + return output + else: + return 'CRASH: %r' % err + +def run_benchmark_on_target(target, script): + output, err = run_script_on_target(target, script) + if err is None: + time, norm, result = output.split(None, 2) + try: + return int(time), int(norm), result + except ValueError: + return -1, -1, 'CRASH: %r' % output + else: + return -1, -1, 'CRASH: %r' % err + +def run_benchmarks(target, param_n, param_m, n_average, test_list): + skip_native = run_feature_test(target, 'native_check') != '' + + for test_file in sorted(test_list): + print(test_file + ': ', end='') + + # Check if test should be skipped + skip = skip_native and test_file.find('viper_') != -1 + if skip: + print('skip') + continue + + # Create test script + with open(test_file, 'rb') as f: + test_script = f.read() + with open(BENCH_SCRIPT_DIR + 'benchrun.py', 'rb') as f: + test_script += f.read() + test_script += b'bm_run(%u, %u)\n' % (param_n, param_m) + + # Write full test script if needed + if 0: + with open('%s.full' % test_file, 'wb') as f: + f.write(test_script) + + # Run MicroPython a given number of times + times = [] + scores = [] + error = None + result_out = None + for _ in range(n_average): + time, norm, result = run_benchmark_on_target(target, test_script) + if time < 0 or norm < 0: + error = result + break + if result_out is None: + result_out = result + elif result != result_out: + error = 'FAIL self' + break + times.append(time) + scores.append(1e6 * norm / time) + + # Check result against truth if needed + if error is None and result_out != 'None': + _, _, result_exp = run_benchmark_on_target(PYTHON_TRUTH, test_script) + if result_out != result_exp: + error = 'FAIL truth' + break + + if error is not None: + print(error) + else: + t_avg, t_sd = compute_stats(times) + s_avg, s_sd = compute_stats(scores) + print('{:.2f} {:.4f} {:.2f} {:.4f}'.format(t_avg, 100 * t_sd / t_avg, s_avg, 100 * s_sd / s_avg)) + if 0: + print(' times: ', times) + print(' scores:', scores) + + sys.stdout.flush() + +def parse_output(filename): + with open(filename) as f: + params = f.readline() + n, m, _ = params.strip().split() + n = int(n.split('=')[1]) + m = int(m.split('=')[1]) + data = [] + for l in f: + if l.find(': ') != -1 and l.find(': skip') == -1 and l.find('CRASH: ') == -1: + name, values = l.strip().split(': ') + values = tuple(float(v) for v in values.split()) + data.append((name,) + values) + return n, m, data + +def compute_diff(file1, file2, diff_score): + # Parse output data from previous runs + n1, m1, d1 = parse_output(file1) + n2, m2, d2 = parse_output(file2) + + # Print header + if diff_score: + print('diff of scores (higher is better)') + else: + print('diff of microsecond times (lower is better)') + if n1 == n2 and m1 == m2: + hdr = 'N={} M={}'.format(n1, m1) + else: + hdr = 'N={} M={} vs N={} M={}'.format(n1, m1, n2, m2) + print('{:24} {:>10} -> {:>10} {:>10} {:>7}% (error%)'.format(hdr, file1, file2, 'diff', 'diff')) + + # Print entries + while d1 and d2: + if d1[0][0] == d2[0][0]: + # Found entries with matching names + entry1 = d1.pop(0) + entry2 = d2.pop(0) + name = entry1[0].rsplit('/')[-1] + av1, sd1 = entry1[1 + 2 * diff_score], entry1[2 + 2 * diff_score] + av2, sd2 = entry2[1 + 2 * diff_score], entry2[2 + 2 * diff_score] + sd1 *= av1 / 100 # convert from percent sd to absolute sd + sd2 *= av2 / 100 # convert from percent sd to absolute sd + av_diff = av2 - av1 + sd_diff = (sd1 ** 2 + sd2 ** 2) ** 0.5 + percent = 100 * av_diff / av1 + percent_sd = 100 * sd_diff / av1 + print('{:24} {:10.2f} -> {:10.2f} : {:+10.2f} = {:+7.3f}% (+/-{:.2f}%)'.format(name, av1, av2, av_diff, percent, percent_sd)) + elif d1[0][0] < d2[0][0]: + d1.pop(0) + else: + d2.pop(0) + +def main(): + cmd_parser = argparse.ArgumentParser(description='Run benchmarks for MicroPython') + cmd_parser.add_argument('-t', '--diff-time', action='store_true', help='diff time outputs from a previous run') + cmd_parser.add_argument('-s', '--diff-score', action='store_true', help='diff score outputs from a previous run') + cmd_parser.add_argument('-p', '--pyboard', action='store_true', help='run tests via pyboard.py') + cmd_parser.add_argument('-d', '--device', default='/dev/ttyACM0', help='the device for pyboard.py') + cmd_parser.add_argument('-a', '--average', default='8', help='averaging number') + cmd_parser.add_argument('N', nargs=1, help='N parameter (approximate target CPU frequency)') + cmd_parser.add_argument('M', nargs=1, help='M parameter (approximate target heap in kbytes)') + cmd_parser.add_argument('files', nargs='*', help='input test files') + args = cmd_parser.parse_args() + + if args.diff_time or args.diff_score: + compute_diff(args.N[0], args.M[0], args.diff_score) + sys.exit(0) + + # N, M = 50, 25 # esp8266 + # N, M = 100, 100 # pyboard, esp32 + # N, M = 1000, 1000 # PC + N = int(args.N[0]) + M = int(args.M[0]) + n_average = int(args.average) + + if args.pyboard: + target = pyboard.Pyboard(args.device) + target.enter_raw_repl() + else: + target = MICROPYTHON + + if len(args.files) == 0: + tests_skip = ('benchrun.py',) + if M <= 25: + # These scripts are too big to be compiled by the target + tests_skip += ('bm_chaos.py', 'bm_hexiom.py', 'misc_raytrace.py') + tests = sorted( + BENCH_SCRIPT_DIR + test_file for test_file in os.listdir(BENCH_SCRIPT_DIR) + if test_file.endswith('.py') and test_file not in tests_skip + ) + else: + tests = sorted(args.files) + + print('N={} M={} n_average={}'.format(N, M, n_average)) + + run_benchmarks(target, N, M, n_average, tests) + + if isinstance(target, pyboard.Pyboard): + target.exit_raw_repl() + target.close() + +if __name__ == "__main__": + main() From 127714c3af73633ba723dad2cf7267131e7ac6c2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 26 Jun 2019 14:24:13 +1000 Subject: [PATCH 0195/1299] tests/perf_bench: Add some benchmarks from python-performance. From https://github.com/python/pyperformance commit 6690642ddeda46fc5ee6e97c3ef4b2f292348ab8 --- tests/perf_bench/bm_chaos.py | 274 ++++++++++++++ tests/perf_bench/bm_fannkuch.py | 67 ++++ tests/perf_bench/bm_float.py | 70 ++++ tests/perf_bench/bm_hexiom.py | 647 ++++++++++++++++++++++++++++++++ tests/perf_bench/bm_nqueens.py | 62 +++ tests/perf_bench/bm_pidigits.py | 62 +++ 6 files changed, 1182 insertions(+) create mode 100644 tests/perf_bench/bm_chaos.py create mode 100644 tests/perf_bench/bm_fannkuch.py create mode 100644 tests/perf_bench/bm_float.py create mode 100644 tests/perf_bench/bm_hexiom.py create mode 100644 tests/perf_bench/bm_nqueens.py create mode 100644 tests/perf_bench/bm_pidigits.py diff --git a/tests/perf_bench/bm_chaos.py b/tests/perf_bench/bm_chaos.py new file mode 100644 index 0000000000000..04e04531cab88 --- /dev/null +++ b/tests/perf_bench/bm_chaos.py @@ -0,0 +1,274 @@ +# Source: https://github.com/python/pyperformance +# License: MIT + +# create chaosgame-like fractals +# Copyright (C) 2005 Carl Friedrich Bolz + +import math +import random + + +class GVector(object): + + def __init__(self, x=0, y=0, z=0): + self.x = x + self.y = y + self.z = z + + def Mag(self): + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) + + def dist(self, other): + return math.sqrt((self.x - other.x) ** 2 + + (self.y - other.y) ** 2 + + (self.z - other.z) ** 2) + + def __add__(self, other): + if not isinstance(other, GVector): + raise ValueError("Can't add GVector to " + str(type(other))) + v = GVector(self.x + other.x, self.y + other.y, self.z + other.z) + return v + + def __sub__(self, other): + return self + other * -1 + + def __mul__(self, other): + v = GVector(self.x * other, self.y * other, self.z * other) + return v + __rmul__ = __mul__ + + def linear_combination(self, other, l1, l2=None): + if l2 is None: + l2 = 1 - l1 + v = GVector(self.x * l1 + other.x * l2, + self.y * l1 + other.y * l2, + self.z * l1 + other.z * l2) + return v + + def __str__(self): + return "<%f, %f, %f>" % (self.x, self.y, self.z) + + def __repr__(self): + return "GVector(%f, %f, %f)" % (self.x, self.y, self.z) + + +class Spline(object): + """Class for representing B-Splines and NURBS of arbitrary degree""" + + def __init__(self, points, degree, knots): + """Creates a Spline. + + points is a list of GVector, degree is the degree of the Spline. + """ + if len(points) > len(knots) - degree + 1: + raise ValueError("too many control points") + elif len(points) < len(knots) - degree + 1: + raise ValueError("not enough control points") + last = knots[0] + for cur in knots[1:]: + if cur < last: + raise ValueError("knots not strictly increasing") + last = cur + self.knots = knots + self.points = points + self.degree = degree + + def GetDomain(self): + """Returns the domain of the B-Spline""" + return (self.knots[self.degree - 1], + self.knots[len(self.knots) - self.degree]) + + def __call__(self, u): + """Calculates a point of the B-Spline using de Boors Algorithm""" + dom = self.GetDomain() + if u < dom[0] or u > dom[1]: + raise ValueError("Function value not in domain") + if u == dom[0]: + return self.points[0] + if u == dom[1]: + return self.points[-1] + I = self.GetIndex(u) + d = [self.points[I - self.degree + 1 + ii] + for ii in range(self.degree + 1)] + U = self.knots + for ik in range(1, self.degree + 1): + for ii in range(I - self.degree + ik + 1, I + 2): + ua = U[ii + self.degree - ik] + ub = U[ii - 1] + co1 = (ua - u) / (ua - ub) + co2 = (u - ub) / (ua - ub) + index = ii - I + self.degree - ik - 1 + d[index] = d[index].linear_combination(d[index + 1], co1, co2) + return d[0] + + def GetIndex(self, u): + dom = self.GetDomain() + for ii in range(self.degree - 1, len(self.knots) - self.degree): + if u >= self.knots[ii] and u < self.knots[ii + 1]: + I = ii + break + else: + I = dom[1] - 1 + return I + + def __len__(self): + return len(self.points) + + def __repr__(self): + return "Spline(%r, %r, %r)" % (self.points, self.degree, self.knots) + + +def write_ppm(im, w, h, filename): + with open(filename, "wb") as f: + f.write(b'P6\n%i %i\n255\n' % (w, h)) + for j in range(h): + for i in range(w): + val = im[j * w + i] + c = val * 255 + f.write(b'%c%c%c' % (c, c, c)) + + +class Chaosgame(object): + + def __init__(self, splines, thickness, subdivs): + self.splines = splines + self.thickness = thickness + self.minx = min([p.x for spl in splines for p in spl.points]) + self.miny = min([p.y for spl in splines for p in spl.points]) + self.maxx = max([p.x for spl in splines for p in spl.points]) + self.maxy = max([p.y for spl in splines for p in spl.points]) + self.height = self.maxy - self.miny + self.width = self.maxx - self.minx + self.num_trafos = [] + maxlength = thickness * self.width / self.height + for spl in splines: + length = 0 + curr = spl(0) + for i in range(1, subdivs + 1): + last = curr + t = 1 / subdivs * i + curr = spl(t) + length += curr.dist(last) + self.num_trafos.append(max(1, int(length / maxlength * 1.5))) + self.num_total = sum(self.num_trafos) + + def get_random_trafo(self): + r = random.randrange(int(self.num_total) + 1) + l = 0 + for i in range(len(self.num_trafos)): + if r >= l and r < l + self.num_trafos[i]: + return i, random.randrange(self.num_trafos[i]) + l += self.num_trafos[i] + return len(self.num_trafos) - 1, random.randrange(self.num_trafos[-1]) + + def transform_point(self, point, trafo=None): + x = (point.x - self.minx) / self.width + y = (point.y - self.miny) / self.height + if trafo is None: + trafo = self.get_random_trafo() + start, end = self.splines[trafo[0]].GetDomain() + length = end - start + seg_length = length / self.num_trafos[trafo[0]] + t = start + seg_length * trafo[1] + seg_length * x + basepoint = self.splines[trafo[0]](t) + if t + 1 / 50000 > end: + neighbour = self.splines[trafo[0]](t - 1 / 50000) + derivative = neighbour - basepoint + else: + neighbour = self.splines[trafo[0]](t + 1 / 50000) + derivative = basepoint - neighbour + if derivative.Mag() != 0: + basepoint.x += derivative.y / derivative.Mag() * (y - 0.5) * \ + self.thickness + basepoint.y += -derivative.x / derivative.Mag() * (y - 0.5) * \ + self.thickness + else: + # can happen, especially with single precision float + pass + self.truncate(basepoint) + return basepoint + + def truncate(self, point): + if point.x >= self.maxx: + point.x = self.maxx + if point.y >= self.maxy: + point.y = self.maxy + if point.x < self.minx: + point.x = self.minx + if point.y < self.miny: + point.y = self.miny + + def create_image_chaos(self, w, h, iterations, rng_seed): + # Always use the same sequence of random numbers + # to get reproductible benchmark + random.seed(rng_seed) + + im = bytearray(w * h) + point = GVector((self.maxx + self.minx) / 2, + (self.maxy + self.miny) / 2, 0) + for _ in range(iterations): + point = self.transform_point(point) + x = (point.x - self.minx) / self.width * w + y = (point.y - self.miny) / self.height * h + x = int(x) + y = int(y) + if x == w: + x -= 1 + if y == h: + y -= 1 + im[(h - y - 1) * w + x] = 1 + + return im + + +########################################################################### +# Benchmark interface + +bm_params = { + (100, 50): (0.25, 100, 50, 50, 50, 1234), + (1000, 1000): (0.25, 200, 400, 400, 1000, 1234), + (5000, 1000): (0.25, 400, 500, 500, 7000, 1234), +} + +def bm_setup(params): + splines = [ + Spline([ + GVector(1.597, 3.304, 0.0), + GVector(1.576, 4.123, 0.0), + GVector(1.313, 5.288, 0.0), + GVector(1.619, 5.330, 0.0), + GVector(2.890, 5.503, 0.0), + GVector(2.373, 4.382, 0.0), + GVector(1.662, 4.360, 0.0)], + 3, [0, 0, 0, 1, 1, 1, 2, 2, 2]), + Spline([ + GVector(2.805, 4.017, 0.0), + GVector(2.551, 3.525, 0.0), + GVector(1.979, 2.620, 0.0), + GVector(1.979, 2.620, 0.0)], + 3, [0, 0, 0, 1, 1, 1]), + Spline([ + GVector(2.002, 4.011, 0.0), + GVector(2.335, 3.313, 0.0), + GVector(2.367, 3.233, 0.0), + GVector(2.367, 3.233, 0.0)], + 3, [0, 0, 0, 1, 1, 1]) + ] + + chaos = Chaosgame(splines, params[0], params[1]) + image = None + + def run(): + nonlocal image + _, _, width, height, iter, rng_seed = params + image = chaos.create_image_chaos(width, height, iter, rng_seed) + + def result(): + norm = params[4] + # Images are not the same when floating point behaviour is different, + # so return percentage of pixels that are set (rounded to int). + #write_ppm(image, params[2], params[3], 'out-.ppm') + pix = int(100 * sum(image) / len(image)) + return norm, pix + + return run, result diff --git a/tests/perf_bench/bm_fannkuch.py b/tests/perf_bench/bm_fannkuch.py new file mode 100644 index 0000000000000..c9782e3e9a732 --- /dev/null +++ b/tests/perf_bench/bm_fannkuch.py @@ -0,0 +1,67 @@ +# Source: https://github.com/python/pyperformance +# License: MIT + +# The Computer Language Benchmarks Game +# http://benchmarksgame.alioth.debian.org/ +# Contributed by Sokolov Yura, modified by Tupteq. + +def fannkuch(n): + count = list(range(1, n + 1)) + max_flips = 0 + m = n - 1 + r = n + check = 0 + perm1 = list(range(n)) + perm = list(range(n)) + perm1_ins = perm1.insert + perm1_pop = perm1.pop + + while 1: + if check < 30: + check += 1 + + while r != 1: + count[r - 1] = r + r -= 1 + + if perm1[0] != 0 and perm1[m] != m: + perm = perm1[:] + flips_count = 0 + k = perm[0] + while k: + perm[:k + 1] = perm[k::-1] + flips_count += 1 + k = perm[0] + + if flips_count > max_flips: + max_flips = flips_count + + while r != n: + perm1_ins(r, perm1_pop(0)) + count[r] -= 1 + if count[r] > 0: + break + r += 1 + else: + return max_flips + + +########################################################################### +# Benchmark interface + +bm_params = { + (50, 10): (5,), + (100, 10): (6,), + (500, 10): (7,), + (1000, 10): (8,), + (5000, 10): (9,), +} + +def bm_setup(params): + state = None + def run(): + nonlocal state + state = fannkuch(params[0]) + def result(): + return params[0], state + return run, result diff --git a/tests/perf_bench/bm_float.py b/tests/perf_bench/bm_float.py new file mode 100644 index 0000000000000..5a66b9bb3e62e --- /dev/null +++ b/tests/perf_bench/bm_float.py @@ -0,0 +1,70 @@ +# Source: https://github.com/python/pyperformance +# License: MIT + +# Artificial, floating point-heavy benchmark originally used by Factor. + +from math import sin, cos, sqrt + + +class Point(object): + __slots__ = ('x', 'y', 'z') + + def __init__(self, i): + self.x = x = sin(i) + self.y = cos(i) * 3 + self.z = (x * x) / 2 + + def __repr__(self): + return "" % (self.x, self.y, self.z) + + def normalize(self): + x = self.x + y = self.y + z = self.z + norm = sqrt(x * x + y * y + z * z) + self.x /= norm + self.y /= norm + self.z /= norm + + def maximize(self, other): + self.x = self.x if self.x > other.x else other.x + self.y = self.y if self.y > other.y else other.y + self.z = self.z if self.z > other.z else other.z + return self + + +def maximize(points): + next = points[0] + for p in points[1:]: + next = next.maximize(p) + return next + + +def benchmark(n): + points = [None] * n + for i in range(n): + points[i] = Point(i) + for p in points: + p.normalize() + return maximize(points) + + +########################################################################### +# Benchmark interface + +bm_params = { + (50, 25): (1, 150), + (100, 100): (1, 250), + (1000, 1000): (10, 1500), + (5000, 1000): (20, 3000), +} + +def bm_setup(params): + state = None + def run(): + nonlocal state + for _ in range(params[0]): + state = benchmark(params[1]) + def result(): + return params[0] * params[1], 'Point(%.4f, %.4f, %.4f)' % (state.x, state.y, state.z) + return run, result diff --git a/tests/perf_bench/bm_hexiom.py b/tests/perf_bench/bm_hexiom.py new file mode 100644 index 0000000000000..3a6f1f6c4bb1d --- /dev/null +++ b/tests/perf_bench/bm_hexiom.py @@ -0,0 +1,647 @@ +# Source: https://github.com/python/pyperformance +# License: MIT + +# Solver of Hexiom board game. +# Benchmark from Laurent Vaucher. +# Source: https://github.com/slowfrog/hexiom : hexiom2.py, level36.txt +# (Main function tweaked by Armin Rigo.) + + +################################## +class Dir(object): + + def __init__(self, x, y): + self.x = x + self.y = y + + +DIRS = [Dir(1, 0), + Dir(-1, 0), + Dir(0, 1), + Dir(0, -1), + Dir(1, 1), + Dir(-1, -1)] + +EMPTY = 7 + +################################## + + +class Done(object): + MIN_CHOICE_STRATEGY = 0 + MAX_CHOICE_STRATEGY = 1 + HIGHEST_VALUE_STRATEGY = 2 + FIRST_STRATEGY = 3 + MAX_NEIGHBORS_STRATEGY = 4 + MIN_NEIGHBORS_STRATEGY = 5 + + def __init__(self, count, empty=False): + self.count = count + self.cells = None if empty else [ + [0, 1, 2, 3, 4, 5, 6, EMPTY] for i in range(count)] + + def clone(self): + ret = Done(self.count, True) + ret.cells = [self.cells[i][:] for i in range(self.count)] + return ret + + def __getitem__(self, i): + return self.cells[i] + + def set_done(self, i, v): + self.cells[i] = [v] + + def already_done(self, i): + return len(self.cells[i]) == 1 + + def remove(self, i, v): + if v in self.cells[i]: + self.cells[i].remove(v) + return True + else: + return False + + def remove_all(self, v): + for i in range(self.count): + self.remove(i, v) + + def remove_unfixed(self, v): + changed = False + for i in range(self.count): + if not self.already_done(i): + if self.remove(i, v): + changed = True + return changed + + def filter_tiles(self, tiles): + for v in range(8): + if tiles[v] == 0: + self.remove_all(v) + + def next_cell_min_choice(self): + minlen = 10 + mini = -1 + for i in range(self.count): + if 1 < len(self.cells[i]) < minlen: + minlen = len(self.cells[i]) + mini = i + return mini + + def next_cell_max_choice(self): + maxlen = 1 + maxi = -1 + for i in range(self.count): + if maxlen < len(self.cells[i]): + maxlen = len(self.cells[i]) + maxi = i + return maxi + + def next_cell_highest_value(self): + maxval = -1 + maxi = -1 + for i in range(self.count): + if (not self.already_done(i)): + maxvali = max(k for k in self.cells[i] if k != EMPTY) + if maxval < maxvali: + maxval = maxvali + maxi = i + return maxi + + def next_cell_first(self): + for i in range(self.count): + if (not self.already_done(i)): + return i + return -1 + + def next_cell_max_neighbors(self, pos): + maxn = -1 + maxi = -1 + for i in range(self.count): + if not self.already_done(i): + cells_around = pos.hex.get_by_id(i).links + n = sum(1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 + for nid in cells_around) + if n > maxn: + maxn = n + maxi = i + return maxi + + def next_cell_min_neighbors(self, pos): + minn = 7 + mini = -1 + for i in range(self.count): + if not self.already_done(i): + cells_around = pos.hex.get_by_id(i).links + n = sum(1 if (self.already_done(nid) and (self[nid][0] != EMPTY)) else 0 + for nid in cells_around) + if n < minn: + minn = n + mini = i + return mini + + def next_cell(self, pos, strategy=HIGHEST_VALUE_STRATEGY): + if strategy == Done.HIGHEST_VALUE_STRATEGY: + return self.next_cell_highest_value() + elif strategy == Done.MIN_CHOICE_STRATEGY: + return self.next_cell_min_choice() + elif strategy == Done.MAX_CHOICE_STRATEGY: + return self.next_cell_max_choice() + elif strategy == Done.FIRST_STRATEGY: + return self.next_cell_first() + elif strategy == Done.MAX_NEIGHBORS_STRATEGY: + return self.next_cell_max_neighbors(pos) + elif strategy == Done.MIN_NEIGHBORS_STRATEGY: + return self.next_cell_min_neighbors(pos) + else: + raise Exception("Wrong strategy: %d" % strategy) + +################################## + + +class Node(object): + + def __init__(self, pos, id, links): + self.pos = pos + self.id = id + self.links = links + +################################## + + +class Hex(object): + + def __init__(self, size): + self.size = size + self.count = 3 * size * (size - 1) + 1 + self.nodes_by_id = self.count * [None] + self.nodes_by_pos = {} + id = 0 + for y in range(size): + for x in range(size + y): + pos = (x, y) + node = Node(pos, id, []) + self.nodes_by_pos[pos] = node + self.nodes_by_id[node.id] = node + id += 1 + for y in range(1, size): + for x in range(y, size * 2 - 1): + ry = size + y - 1 + pos = (x, ry) + node = Node(pos, id, []) + self.nodes_by_pos[pos] = node + self.nodes_by_id[node.id] = node + id += 1 + + def link_nodes(self): + for node in self.nodes_by_id: + (x, y) = node.pos + for dir in DIRS: + nx = x + dir.x + ny = y + dir.y + if self.contains_pos((nx, ny)): + node.links.append(self.nodes_by_pos[(nx, ny)].id) + + def contains_pos(self, pos): + return pos in self.nodes_by_pos + + def get_by_pos(self, pos): + return self.nodes_by_pos[pos] + + def get_by_id(self, id): + return self.nodes_by_id[id] + + +################################## +class Pos(object): + + def __init__(self, hex, tiles, done=None): + self.hex = hex + self.tiles = tiles + self.done = Done(hex.count) if done is None else done + + def clone(self): + return Pos(self.hex, self.tiles, self.done.clone()) + +################################## + + +def constraint_pass(pos, last_move=None): + changed = False + left = pos.tiles[:] + done = pos.done + + # Remove impossible values from free cells + free_cells = (range(done.count) if last_move is None + else pos.hex.get_by_id(last_move).links) + for i in free_cells: + if not done.already_done(i): + vmax = 0 + vmin = 0 + cells_around = pos.hex.get_by_id(i).links + for nid in cells_around: + if done.already_done(nid): + if done[nid][0] != EMPTY: + vmin += 1 + vmax += 1 + else: + vmax += 1 + + for num in range(7): + if (num < vmin) or (num > vmax): + if done.remove(i, num): + changed = True + + # Computes how many of each value is still free + for cell in done.cells: + if len(cell) == 1: + left[cell[0]] -= 1 + + for v in range(8): + # If there is none, remove the possibility from all tiles + if (pos.tiles[v] > 0) and (left[v] == 0): + if done.remove_unfixed(v): + changed = True + else: + possible = sum((1 if v in cell else 0) for cell in done.cells) + # If the number of possible cells for a value is exactly the number of available tiles + # put a tile in each cell + if pos.tiles[v] == possible: + for i in range(done.count): + cell = done.cells[i] + if (not done.already_done(i)) and (v in cell): + done.set_done(i, v) + changed = True + + # Force empty or non-empty around filled cells + filled_cells = (range(done.count) if last_move is None + else [last_move]) + for i in filled_cells: + if done.already_done(i): + num = done[i][0] + empties = 0 + filled = 0 + unknown = [] + cells_around = pos.hex.get_by_id(i).links + for nid in cells_around: + if done.already_done(nid): + if done[nid][0] == EMPTY: + empties += 1 + else: + filled += 1 + else: + unknown.append(nid) + if len(unknown) > 0: + if num == filled: + for u in unknown: + if EMPTY in done[u]: + done.set_done(u, EMPTY) + changed = True + # else: + # raise Exception("Houston, we've got a problem") + elif num == filled + len(unknown): + for u in unknown: + if done.remove(u, EMPTY): + changed = True + + return changed + + +ASCENDING = 1 +DESCENDING = -1 + + +def find_moves(pos, strategy, order): + done = pos.done + cell_id = done.next_cell(pos, strategy) + if cell_id < 0: + return [] + + if order == ASCENDING: + return [(cell_id, v) for v in done[cell_id]] + else: + # Try higher values first and EMPTY last + moves = list(reversed([(cell_id, v) + for v in done[cell_id] if v != EMPTY])) + if EMPTY in done[cell_id]: + moves.append((cell_id, EMPTY)) + return moves + + +def play_move(pos, move): + (cell_id, i) = move + pos.done.set_done(cell_id, i) + + +def print_pos(pos, output): + hex = pos.hex + done = pos.done + size = hex.size + for y in range(size): + print(" " * (size - y - 1), end="", file=output) + for x in range(size + y): + pos2 = (x, y) + id = hex.get_by_pos(pos2).id + if done.already_done(id): + c = done[id][0] if done[id][0] != EMPTY else "." + else: + c = "?" + print("%s " % c, end="", file=output) + print(end="\n", file=output) + for y in range(1, size): + print(" " * y, end="", file=output) + for x in range(y, size * 2 - 1): + ry = size + y - 1 + pos2 = (x, ry) + id = hex.get_by_pos(pos2).id + if done.already_done(id): + c = done[id][0] if done[id][0] != EMPTY else "." + else: + c = "?" + print("%s " % c, end="", file=output) + print(end="\n", file=output) + + +OPEN = 0 +SOLVED = 1 +IMPOSSIBLE = -1 + + +def solved(pos, output, verbose=False): + hex = pos.hex + tiles = pos.tiles[:] + done = pos.done + exact = True + all_done = True + for i in range(hex.count): + if len(done[i]) == 0: + return IMPOSSIBLE + elif done.already_done(i): + num = done[i][0] + tiles[num] -= 1 + if (tiles[num] < 0): + return IMPOSSIBLE + vmax = 0 + vmin = 0 + if num != EMPTY: + cells_around = hex.get_by_id(i).links + for nid in cells_around: + if done.already_done(nid): + if done[nid][0] != EMPTY: + vmin += 1 + vmax += 1 + else: + vmax += 1 + + if (num < vmin) or (num > vmax): + return IMPOSSIBLE + if num != vmin: + exact = False + else: + all_done = False + + if (not all_done) or (not exact): + return OPEN + + print_pos(pos, output) + return SOLVED + + +def solve_step(prev, strategy, order, output, first=False): + if first: + pos = prev.clone() + while constraint_pass(pos): + pass + else: + pos = prev + + moves = find_moves(pos, strategy, order) + if len(moves) == 0: + return solved(pos, output) + else: + for move in moves: + # print("Trying (%d, %d)" % (move[0], move[1])) + ret = OPEN + new_pos = pos.clone() + play_move(new_pos, move) + # print_pos(new_pos) + while constraint_pass(new_pos, move[0]): + pass + cur_status = solved(new_pos, output) + if cur_status != OPEN: + ret = cur_status + else: + ret = solve_step(new_pos, strategy, order, output) + if ret == SOLVED: + return SOLVED + return IMPOSSIBLE + + +def check_valid(pos): + hex = pos.hex + tiles = pos.tiles + # fill missing entries in tiles + tot = 0 + for i in range(8): + if tiles[i] > 0: + tot += tiles[i] + else: + tiles[i] = 0 + # check total + if tot != hex.count: + raise Exception( + "Invalid input. Expected %d tiles, got %d." % (hex.count, tot)) + + +def solve(pos, strategy, order, output): + check_valid(pos) + return solve_step(pos, strategy, order, output, first=True) + + +# TODO Write an 'iterator' to go over all x,y positions + +def read_file(file): + lines = [line.strip("\r\n") for line in file.splitlines()] + size = int(lines[0]) + hex = Hex(size) + linei = 1 + tiles = 8 * [0] + done = Done(hex.count) + for y in range(size): + line = lines[linei][size - y - 1:] + p = 0 + for x in range(size + y): + tile = line[p:p + 2] + p += 2 + if tile[1] == ".": + inctile = EMPTY + else: + inctile = int(tile) + tiles[inctile] += 1 + # Look for locked tiles + if tile[0] == "+": + # print("Adding locked tile: %d at pos %d, %d, id=%d" % + # (inctile, x, y, hex.get_by_pos((x, y)).id)) + done.set_done(hex.get_by_pos((x, y)).id, inctile) + + linei += 1 + for y in range(1, size): + ry = size - 1 + y + line = lines[linei][y:] + p = 0 + for x in range(y, size * 2 - 1): + tile = line[p:p + 2] + p += 2 + if tile[1] == ".": + inctile = EMPTY + else: + inctile = int(tile) + tiles[inctile] += 1 + # Look for locked tiles + if tile[0] == "+": + # print("Adding locked tile: %d at pos %d, %d, id=%d" % + # (inctile, x, ry, hex.get_by_pos((x, ry)).id)) + done.set_done(hex.get_by_pos((x, ry)).id, inctile) + linei += 1 + hex.link_nodes() + done.filter_tiles(tiles) + return Pos(hex, tiles, done) + + +def solve_file(file, strategy, order, output): + pos = read_file(file) + solve(pos, strategy, order, output) + + +LEVELS = {} + +LEVELS[2] = (""" +2 + . 1 + . 1 1 + 1 . +""", """\ + 1 1 +. . . + 1 1 +""") + +LEVELS[10] = (""" +3 + +.+. . + +. 0 . 2 + . 1+2 1 . + 2 . 0+. + .+.+. +""", """\ + . . 1 + . 1 . 2 +0 . 2 2 . + . . . . + 0 . . +""") + +LEVELS[20] = (""" +3 + . 5 4 + . 2+.+1 + . 3+2 3 . + +2+. 5 . + . 3 . +""", """\ + 3 3 2 + 4 5 . 1 +3 5 2 . . + 2 . . . + . . . +""") + +LEVELS[25] = (""" +3 + 4 . . + . . 2 . + 4 3 2 . 4 + 2 2 3 . + 4 2 4 +""", """\ + 3 4 2 + 2 4 4 . +. . . 4 2 + . 2 4 3 + . 2 . +""") + +LEVELS[30] = (""" +4 + 5 5 . . + 3 . 2+2 6 + 3 . 2 . 5 . + . 3 3+4 4 . 3 + 4 5 4 . 5 4 + 5+2 . . 3 + 4 . . . +""", """\ + 3 4 3 . + 4 6 5 2 . + 2 5 5 . . 2 +. . 5 4 . 4 3 + . 3 5 4 5 4 + . 2 . 3 3 + . . . . +""") + +LEVELS[36] = (""" +4 + 2 1 1 2 + 3 3 3 . . + 2 3 3 . 4 . + . 2 . 2 4 3 2 + 2 2 . . . 2 + 4 3 4 . . + 3 2 3 3 +""", """\ + 3 4 3 2 + 3 4 4 . 3 + 2 . . 3 4 3 +2 . 1 . 3 . 2 + 3 3 . 2 . 2 + 3 . 2 . 2 + 2 2 . 1 +""") + + +########################################################################### +# Benchmark interface + +bm_params = { + (100, 100): (1, 10, DESCENDING, Done.FIRST_STRATEGY), + (1000, 1000): (1, 25, DESCENDING, Done.FIRST_STRATEGY), + (5000, 1000): (10, 25, DESCENDING, Done.FIRST_STRATEGY), +} + +def bm_setup(params): + try: + import uio as io + except ImportError: + import io + + loops, level, order, strategy = params + + board, solution = LEVELS[level] + board = board.strip() + expected = solution.rstrip() + output = None + + def run(): + nonlocal output + for _ in range(loops): + stream = io.StringIO() + solve_file(board, strategy, order, stream) + output = stream.getvalue() + stream = None + + def result(): + norm = params[0] * params[1] + out = '\n'.join(line.rstrip() for line in output.splitlines()) + return norm, ((out == expected), out) + + return run, result diff --git a/tests/perf_bench/bm_nqueens.py b/tests/perf_bench/bm_nqueens.py new file mode 100644 index 0000000000000..87e7245c04aef --- /dev/null +++ b/tests/perf_bench/bm_nqueens.py @@ -0,0 +1,62 @@ +# Source: https://github.com/python/pyperformance +# License: MIT + +# Simple, brute-force N-Queens solver. +# author: collinwinter@google.com (Collin Winter) +# n_queens function: Copyright 2009 Raymond Hettinger + +# Pure-Python implementation of itertools.permutations(). +def permutations(iterable, r=None): + """permutations(range(3), 2) --> (0,1) (0,2) (1,0) (1,2) (2,0) (2,1)""" + pool = tuple(iterable) + n = len(pool) + if r is None: + r = n + indices = list(range(n)) + cycles = list(range(n - r + 1, n + 1))[::-1] + yield tuple(pool[i] for i in indices[:r]) + while n: + for i in reversed(range(r)): + cycles[i] -= 1 + if cycles[i] == 0: + indices[i:] = indices[i + 1:] + indices[i:i + 1] + cycles[i] = n - i + else: + j = cycles[i] + indices[i], indices[-j] = indices[-j], indices[i] + yield tuple(pool[i] for i in indices[:r]) + break + else: + return + +# From http://code.activestate.com/recipes/576647/ +def n_queens(queen_count): + """N-Queens solver. + Args: queen_count: the number of queens to solve for, same as board size. + Yields: Solutions to the problem, each yielded value is a N-tuple. + """ + cols = range(queen_count) + for vec in permutations(cols): + if (queen_count == len(set(vec[i] + i for i in cols)) + == len(set(vec[i] - i for i in cols))): + yield vec + +########################################################################### +# Benchmark interface + +bm_params = { + (50, 25): (1, 5), + (100, 25): (1, 6), + (1000, 100): (1, 7), + (5000, 100): (1, 8), +} + +def bm_setup(params): + res = None + def run(): + nonlocal res + for _ in range(params[0]): + res = len(list(n_queens(params[1]))) + def result(): + return params[0] * 10 ** (params[1] - 3), res + return run, result diff --git a/tests/perf_bench/bm_pidigits.py b/tests/perf_bench/bm_pidigits.py new file mode 100644 index 0000000000000..ca2e5297d01af --- /dev/null +++ b/tests/perf_bench/bm_pidigits.py @@ -0,0 +1,62 @@ +# Source: https://github.com/python/pyperformance +# License: MIT + +# Calculating some of the digits of π. +# This benchmark stresses big integer arithmetic. +# Adapted from code on: http://benchmarksgame.alioth.debian.org/ + + +def compose(a, b): + aq, ar, as_, at = a + bq, br, bs, bt = b + return (aq * bq, + aq * br + ar * bt, + as_ * bq + at * bs, + as_ * br + at * bt) + + +def extract(z, j): + q, r, s, t = z + return (q * j + r) // (s * j + t) + + +def gen_pi_digits(n): + z = (1, 0, 0, 1) + k = 1 + digs = [] + for _ in range(n): + y = extract(z, 3) + while y != extract(z, 4): + z = compose(z, (k, 4 * k + 2, 0, 2 * k + 1)) + k += 1 + y = extract(z, 3) + z = compose((10, -10 * y, 0, 1), z) + digs.append(y) + return digs + + +########################################################################### +# Benchmark interface + +bm_params = { + (50, 25): (1, 35), + (100, 100): (1, 65), + (1000, 1000): (2, 250), + (5000, 1000): (3, 350), +} + +def bm_setup(params): + state = None + + def run(): + nonlocal state + nloop, ndig = params + ndig = params[1] + for _ in range(nloop): + state = None # free previous result + state = gen_pi_digits(ndig) + + def result(): + return params[0] * params[1], ''.join(str(d) for d in state) + + return run, result From 73c269414f41dac87122963dc1fc456442de8b85 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 26 Jun 2019 14:26:20 +1000 Subject: [PATCH 0196/1299] tests/perf_bench: Add some miscellaneous performance benchmarks. misc_aes.py and misc_mandel.py are adapted from sources in this repository. misc_pystone.py is the standard Python pystone test. misc_raytrace.py is written from scratch. --- tests/perf_bench/misc_aes.py | 225 +++++++++++++++++++++++++++ tests/perf_bench/misc_mandel.py | 31 ++++ tests/perf_bench/misc_pystone.py | 226 ++++++++++++++++++++++++++++ tests/perf_bench/misc_raytrace.py | 242 ++++++++++++++++++++++++++++++ 4 files changed, 724 insertions(+) create mode 100644 tests/perf_bench/misc_aes.py create mode 100644 tests/perf_bench/misc_mandel.py create mode 100644 tests/perf_bench/misc_pystone.py create mode 100644 tests/perf_bench/misc_raytrace.py diff --git a/tests/perf_bench/misc_aes.py b/tests/perf_bench/misc_aes.py new file mode 100644 index 0000000000000..5413a06b12b19 --- /dev/null +++ b/tests/perf_bench/misc_aes.py @@ -0,0 +1,225 @@ +# Pure Python AES encryption routines. +# +# AES is integer based and inplace so doesn't use the heap. It is therefore +# a good test of raw performance and correctness of the VM/runtime. +# +# The AES code comes first (code originates from a C version authored by D.P.George) +# and then the test harness at the bottom. +# +# MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd + +################################################################## +# discrete arithmetic routines, mostly from a precomputed table + +# non-linear, invertible, substitution box +aes_s_box_table = bytes(( + 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, + 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, + 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, + 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, + 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, + 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, + 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, + 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, + 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, + 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, + 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, + 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, + 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, + 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, + 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, + 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16, +)) + +# multiplication of polynomials modulo x^8 + x^4 + x^3 + x + 1 = 0x11b +def aes_gf8_mul_2(x): + if x & 0x80: + return (x << 1) ^ 0x11b + else: + return x << 1 + +def aes_gf8_mul_3(x): + return x ^ aes_gf8_mul_2(x) + +# non-linear, invertible, substitution box +def aes_s_box(a): + return aes_s_box_table[a & 0xff] + +# return 0x02^(a-1) in GF(2^8) +def aes_r_con(a): + ans = 1 + while a > 1: + ans <<= 1; + if ans & 0x100: + ans ^= 0x11b + a -= 1 + return ans + +################################################################## +# basic AES algorithm; see FIPS-197 + +# all inputs must be size 16 +def aes_add_round_key(state, w): + for i in range(16): + state[i] ^= w[i] + +# combined sub_bytes, shift_rows, mix_columns, add_round_key +# all inputs must be size 16 +def aes_sb_sr_mc_ark(state, w, w_idx, temp): + temp_idx = 0 + for i in range(4): + x0 = aes_s_box_table[state[i * 4]] + x1 = aes_s_box_table[state[1 + ((i + 1) & 3) * 4]] + x2 = aes_s_box_table[state[2 + ((i + 2) & 3) * 4]] + x3 = aes_s_box_table[state[3 + ((i + 3) & 3) * 4]] + temp[temp_idx] = aes_gf8_mul_2(x0) ^ aes_gf8_mul_3(x1) ^ x2 ^ x3 ^ w[w_idx] + temp[temp_idx + 1] = x0 ^ aes_gf8_mul_2(x1) ^ aes_gf8_mul_3(x2) ^ x3 ^ w[w_idx + 1] + temp[temp_idx + 2] = x0 ^ x1 ^ aes_gf8_mul_2(x2) ^ aes_gf8_mul_3(x3) ^ w[w_idx + 2] + temp[temp_idx + 3] = aes_gf8_mul_3(x0) ^ x1 ^ x2 ^ aes_gf8_mul_2(x3) ^ w[w_idx + 3] + w_idx += 4 + temp_idx += 4 + for i in range(16): + state[i] = temp[i] + +# combined sub_bytes, shift_rows, add_round_key +# all inputs must be size 16 +def aes_sb_sr_ark(state, w, w_idx, temp): + temp_idx = 0 + for i in range(4): + x0 = aes_s_box_table[state[i * 4]] + x1 = aes_s_box_table[state[1 + ((i + 1) & 3) * 4]] + x2 = aes_s_box_table[state[2 + ((i + 2) & 3) * 4]] + x3 = aes_s_box_table[state[3 + ((i + 3) & 3) * 4]] + temp[temp_idx] = x0 ^ w[w_idx] + temp[temp_idx + 1] = x1 ^ w[w_idx + 1] + temp[temp_idx + 2] = x2 ^ w[w_idx + 2] + temp[temp_idx + 3] = x3 ^ w[w_idx + 3] + w_idx += 4 + temp_idx += 4 + for i in range(16): + state[i] = temp[i] + +# take state as input and change it to the next state in the sequence +# state and temp have size 16, w has size 16 * (Nr + 1), Nr >= 1 +def aes_state(state, w, temp, nr): + aes_add_round_key(state, w) + w_idx = 16 + for i in range(nr - 1): + aes_sb_sr_mc_ark(state, w, w_idx, temp) + w_idx += 16 + aes_sb_sr_ark(state, w, w_idx, temp) + +# expand 'key' to 'w' for use with aes_state +# key has size 4 * Nk, w has size 16 * (Nr + 1), temp has size 16 +def aes_key_expansion(key, w, temp, nk, nr): + for i in range(4 * nk): + w[i] = key[i] + w_idx = 4 * nk - 4 + for i in range(nk, 4 * (nr + 1)): + t = temp + t_idx = 0 + if i % nk == 0: + t[0] = aes_s_box(w[w_idx + 1]) ^ aes_r_con(i // nk) + for j in range(1, 4): + t[j] = aes_s_box(w[w_idx + (j + 1) % 4]) + elif nk > 6 and i % nk == 4: + for j in range(0, 4): + t[j] = aes_s_box(w[w_idx + j]) + else: + t = w + t_idx = w_idx + w_idx += 4 + for j in range(4): + w[w_idx + j] = w[w_idx + j - 4 * nk] ^ t[t_idx + j] + +################################################################## +# simple use of AES algorithm, using output feedback (OFB) mode + +class AES: + def __init__(self, keysize): + if keysize == 128: + self.nk = 4 + self.nr = 10 + elif keysize == 192: + self.nk = 6 + self.nr = 12 + else: + assert keysize == 256 + self.nk = 8 + self.nr = 14 + + self.state = bytearray(16) + self.w = bytearray(16 * (self.nr + 1)) + self.temp = bytearray(16) + self.state_pos = 16 + + def set_key(self, key): + aes_key_expansion(key, self.w, self.temp, self.nk, self.nr) + self.state_pos = 16 + + def set_iv(self, iv): + for i in range(16): + self.state[i] = iv[i] + self.state_pos = 16; + + def get_some_state(self, n_needed): + if self.state_pos >= 16: + aes_state(self.state, self.w, self.temp, self.nr) + self.state_pos = 0 + n = 16 - self.state_pos + if n > n_needed: + n = n_needed + return n + + def apply_to(self, data): + idx = 0 + n = len(data) + while n > 0: + ln = self.get_some_state(n) + n -= ln + for i in range(ln): + data[idx + i] ^= self.state[self.state_pos + i] + idx += ln + self.state_pos += n + +########################################################################### +# Benchmark interface + +bm_params = { + (50, 25): (1, 16), + (100, 100): (1, 32), + (1000, 1000): (4, 256), + (5000, 1000): (20, 256), +} + +def bm_setup(params): + nloop, datalen = params + + aes = AES(256) + key = bytearray(256 // 8) + iv = bytearray(16) + data = bytearray(datalen) + # from now on we don't use the heap + + def run(): + for loop in range(nloop): + # encrypt + aes.set_key(key) + aes.set_iv(iv) + for i in range(2): + aes.apply_to(data) + + # decrypt + aes.set_key(key) + aes.set_iv(iv) + for i in range(2): + aes.apply_to(data) + + # verify + for i in range(len(data)): + assert data[i] == 0 + + def result(): + return params[0] * params[1], True + + return run, result diff --git a/tests/perf_bench/misc_mandel.py b/tests/perf_bench/misc_mandel.py new file mode 100644 index 0000000000000..a4b789136d9d1 --- /dev/null +++ b/tests/perf_bench/misc_mandel.py @@ -0,0 +1,31 @@ +# Compute the Mandelbrot set, to test complex numbers + +def mandelbrot(w, h): + def in_set(c): + z = 0 + for i in range(32): + z = z * z + c + if abs(z) > 100: + return i + return 0 + + img = bytearray(w * h) + + xscale = ((w - 1) / 2.4) + yscale = ((h - 1) / 3.2) + for v in range(h): + line = memoryview(img)[v * w:v * w + w] + for u in range(w): + c = in_set(complex(v / yscale - 2.3, u / xscale - 1.2)) + line[u] = c + + return img + +bm_params = { + (100, 100): (20, 20), + (1000, 1000): (80, 80), + (5000, 1000): (150, 150), +} + +def bm_setup(ps): + return lambda: mandelbrot(ps[0], ps[1]), lambda: (ps[0] * ps[1], None) diff --git a/tests/perf_bench/misc_pystone.py b/tests/perf_bench/misc_pystone.py new file mode 100644 index 0000000000000..88626774b254a --- /dev/null +++ b/tests/perf_bench/misc_pystone.py @@ -0,0 +1,226 @@ +""" +"PYSTONE" Benchmark Program + +Version: Python/1.2 (corresponds to C/1.1 plus 3 Pystone fixes) + +Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013. + + Translated from ADA to C by Rick Richardson. + Every method to preserve ADA-likeness has been used, + at the expense of C-ness. + + Translated from C to Python by Guido van Rossum. +""" + +__version__ = "1.2" + +[Ident1, Ident2, Ident3, Ident4, Ident5] = range(1, 6) + +class Record: + + def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0, + IntComp = 0, StringComp = 0): + self.PtrComp = PtrComp + self.Discr = Discr + self.EnumComp = EnumComp + self.IntComp = IntComp + self.StringComp = StringComp + + def copy(self): + return Record(self.PtrComp, self.Discr, self.EnumComp, + self.IntComp, self.StringComp) + +TRUE = 1 +FALSE = 0 + +def Setup(): + global IntGlob + global BoolGlob + global Char1Glob + global Char2Glob + global Array1Glob + global Array2Glob + + IntGlob = 0 + BoolGlob = FALSE + Char1Glob = '\0' + Char2Glob = '\0' + Array1Glob = [0]*51 + Array2Glob = [x[:] for x in [Array1Glob]*51] + +def Proc0(loops): + global IntGlob + global BoolGlob + global Char1Glob + global Char2Glob + global Array1Glob + global Array2Glob + global PtrGlb + global PtrGlbNext + + PtrGlbNext = Record() + PtrGlb = Record() + PtrGlb.PtrComp = PtrGlbNext + PtrGlb.Discr = Ident1 + PtrGlb.EnumComp = Ident3 + PtrGlb.IntComp = 40 + PtrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING" + String1Loc = "DHRYSTONE PROGRAM, 1'ST STRING" + Array2Glob[8][7] = 10 + + for i in range(loops): + Proc5() + Proc4() + IntLoc1 = 2 + IntLoc2 = 3 + String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING" + EnumLoc = Ident2 + BoolGlob = not Func2(String1Loc, String2Loc) + while IntLoc1 < IntLoc2: + IntLoc3 = 5 * IntLoc1 - IntLoc2 + IntLoc3 = Proc7(IntLoc1, IntLoc2) + IntLoc1 = IntLoc1 + 1 + Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3) + PtrGlb = Proc1(PtrGlb) + CharIndex = 'A' + while CharIndex <= Char2Glob: + if EnumLoc == Func1(CharIndex, 'C'): + EnumLoc = Proc6(Ident1) + CharIndex = chr(ord(CharIndex)+1) + IntLoc3 = IntLoc2 * IntLoc1 + IntLoc2 = IntLoc3 // IntLoc1 + IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1 + IntLoc1 = Proc2(IntLoc1) + +def Proc1(PtrParIn): + PtrParIn.PtrComp = NextRecord = PtrGlb.copy() + PtrParIn.IntComp = 5 + NextRecord.IntComp = PtrParIn.IntComp + NextRecord.PtrComp = PtrParIn.PtrComp + NextRecord.PtrComp = Proc3(NextRecord.PtrComp) + if NextRecord.Discr == Ident1: + NextRecord.IntComp = 6 + NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) + NextRecord.PtrComp = PtrGlb.PtrComp + NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) + else: + PtrParIn = NextRecord.copy() + NextRecord.PtrComp = None + return PtrParIn + +def Proc2(IntParIO): + IntLoc = IntParIO + 10 + while 1: + if Char1Glob == 'A': + IntLoc = IntLoc - 1 + IntParIO = IntLoc - IntGlob + EnumLoc = Ident1 + if EnumLoc == Ident1: + break + return IntParIO + +def Proc3(PtrParOut): + global IntGlob + + if PtrGlb is not None: + PtrParOut = PtrGlb.PtrComp + else: + IntGlob = 100 + PtrGlb.IntComp = Proc7(10, IntGlob) + return PtrParOut + +def Proc4(): + global Char2Glob + + BoolLoc = Char1Glob == 'A' + BoolLoc = BoolLoc or BoolGlob + Char2Glob = 'B' + +def Proc5(): + global Char1Glob + global BoolGlob + + Char1Glob = 'A' + BoolGlob = FALSE + +def Proc6(EnumParIn): + EnumParOut = EnumParIn + if not Func3(EnumParIn): + EnumParOut = Ident4 + if EnumParIn == Ident1: + EnumParOut = Ident1 + elif EnumParIn == Ident2: + if IntGlob > 100: + EnumParOut = Ident1 + else: + EnumParOut = Ident4 + elif EnumParIn == Ident3: + EnumParOut = Ident2 + elif EnumParIn == Ident4: + pass + elif EnumParIn == Ident5: + EnumParOut = Ident3 + return EnumParOut + +def Proc7(IntParI1, IntParI2): + IntLoc = IntParI1 + 2 + IntParOut = IntParI2 + IntLoc + return IntParOut + +def Proc8(Array1Par, Array2Par, IntParI1, IntParI2): + global IntGlob + + IntLoc = IntParI1 + 5 + Array1Par[IntLoc] = IntParI2 + Array1Par[IntLoc+1] = Array1Par[IntLoc] + Array1Par[IntLoc+30] = IntLoc + for IntIndex in range(IntLoc, IntLoc+2): + Array2Par[IntLoc][IntIndex] = IntLoc + Array2Par[IntLoc][IntLoc-1] = Array2Par[IntLoc][IntLoc-1] + 1 + Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc] + IntGlob = 5 + +def Func1(CharPar1, CharPar2): + CharLoc1 = CharPar1 + CharLoc2 = CharLoc1 + if CharLoc2 != CharPar2: + return Ident1 + else: + return Ident2 + +def Func2(StrParI1, StrParI2): + IntLoc = 1 + while IntLoc <= 1: + if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: + CharLoc = 'A' + IntLoc = IntLoc + 1 + if CharLoc >= 'W' and CharLoc <= 'Z': + IntLoc = 7 + if CharLoc == 'X': + return TRUE + else: + if StrParI1 > StrParI2: + IntLoc = IntLoc + 7 + return TRUE + else: + return FALSE + +def Func3(EnumParIn): + EnumLoc = EnumParIn + if EnumLoc == Ident3: return TRUE + return FALSE + + +########################################################################### +# Benchmark interface + +bm_params = { + (50, 10): (80,), + (100, 10): (300,), + (1000, 10): (4000,), + (5000, 10): (20000,), +} + +def bm_setup(params): + Setup() + return lambda: Proc0(params[0]), lambda: (params[0], 0) diff --git a/tests/perf_bench/misc_raytrace.py b/tests/perf_bench/misc_raytrace.py new file mode 100644 index 0000000000000..76d4194bceb3b --- /dev/null +++ b/tests/perf_bench/misc_raytrace.py @@ -0,0 +1,242 @@ +# A simple ray tracer +# MIT license; Copyright (c) 2019 Damien P. George + +INF = 1e30 +EPS = 1e-6 + +class Vec: + def __init__(self, x, y, z): + self.x, self.y, self.z = x, y, z + + def __neg__(self): + return Vec(-self.x, -self.y, -self.z) + + def __add__(self, rhs): + return Vec(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z) + + def __sub__(self, rhs): + return Vec(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z) + + def __mul__(self, rhs): + return Vec(self.x * rhs, self.y * rhs, self.z * rhs) + + def length(self): + return (self.x ** 2 + self.y ** 2 + self.z ** 2) ** 0.5 + + def normalise(self): + l = self.length() + return Vec(self.x / l, self.y / l, self.z / l) + + def dot(self, rhs): + return self.x * rhs.x + self.y * rhs.y + self.z * rhs.z + +RGB = Vec + +class Ray: + def __init__(self, p, d): + self.p, self.d = p, d + +class View: + def __init__(self, width, height, depth, pos, xdir, ydir, zdir): + self.width = width + self.height = height + self.depth = depth + self.pos = pos + self.xdir = xdir + self.ydir = ydir + self.zdir = zdir + + def calc_dir(self, dx, dy): + return (self.xdir * dx + self.ydir * dy + self.zdir * self.depth).normalise() + +class Light: + def __init__(self, pos, colour, casts_shadows): + self.pos = pos + self.colour = colour + self.casts_shadows = casts_shadows + +class Surface: + def __init__(self, diffuse, specular, spec_idx, reflect, transp, colour): + self.diffuse = diffuse + self.specular = specular + self.spec_idx = spec_idx + self.reflect = reflect + self.transp = transp + self.colour = colour + + @staticmethod + def dull(colour): + return Surface(0.7, 0.0, 1, 0.0, 0.0, colour * 0.6) + + @staticmethod + def shiny(colour): + return Surface(0.2, 0.9, 32, 0.8, 0.0, colour * 0.3) + + @staticmethod + def transparent(colour): + return Surface(0.2, 0.9, 32, 0.0, 0.8, colour * 0.3) + +class Sphere: + def __init__(self, surface, centre, radius): + self.surface = surface + self.centre = centre + self.radsq = radius ** 2 + + def intersect(self, ray): + v = self.centre - ray.p + b = v.dot(ray.d) + det = b ** 2 - v.dot(v) + self.radsq + if det > 0: + det **= 0.5 + t1 = b - det + if t1 > EPS: + return t1 + t2 = b + det + if t2 > EPS: + return t2 + return INF + + def surface_at(self, v): + return self.surface, (v - self.centre).normalise() + +class Plane: + def __init__(self, surface, centre, normal): + self.surface = surface + self.normal = normal.normalise() + self.cdotn = centre.dot(normal) + + def intersect(self, ray): + ddotn = ray.d.dot(self.normal) + if abs(ddotn) > EPS: + t = (self.cdotn - ray.p.dot(self.normal)) / ddotn + if t > 0: + return t + return INF + + def surface_at(self, p): + return self.surface, self.normal + +class Scene: + def __init__(self, ambient, light, objs): + self.ambient = ambient + self.light = light + self.objs = objs + +def trace_scene(canvas, view, scene, max_depth): + for v in range(canvas.height): + y = (-v + 0.5 * (canvas.height - 1)) * view.height / canvas.height + for u in range(canvas.width): + x = (u - 0.5 * (canvas.width - 1)) * view.width / canvas.width + ray = Ray(view.pos, view.calc_dir(x, y)) + c = trace_ray(scene, ray, max_depth) + canvas.put_pix(u, v, c) + +def trace_ray(scene, ray, depth): + # Find closest intersecting object + hit_t = INF + hit_obj = None + for obj in scene.objs: + t = obj.intersect(ray) + if t < hit_t: + hit_t = t + hit_obj = obj + + # Check if any objects hit + if hit_obj is None: + return RGB(0, 0, 0) + + # Compute location of ray intersection + point = ray.p + ray.d * hit_t + surf, surf_norm = hit_obj.surface_at(point) + if ray.d.dot(surf_norm) > 0: + surf_norm = -surf_norm + + # Compute reflected ray + reflected = ray.d - surf_norm * (surf_norm.dot(ray.d) * 2) + + # Ambient light + col = surf.colour * scene.ambient + + # Diffuse, specular and shadow from light source + light_vec = scene.light.pos - point + light_dist = light_vec.length() + light_vec = light_vec.normalise() + ndotl = surf_norm.dot(light_vec) + ldotv = light_vec.dot(reflected) + if ndotl > 0 or ldotv > 0: + light_ray = Ray(point + light_vec * EPS, light_vec) + light_col = trace_to_light(scene, light_ray, light_dist) + if ndotl > 0: + col += light_col * surf.diffuse * ndotl + if ldotv > 0: + col += light_col * surf.specular * ldotv ** surf.spec_idx + + # Reflections + if depth > 0 and surf.reflect > 0: + col += trace_ray(scene, Ray(point + reflected * EPS, reflected), depth - 1) * surf.reflect + + # Transparency + if depth > 0 and surf.transp > 0: + col += trace_ray(scene, Ray(point + ray.d * EPS, ray.d), depth - 1) * surf.transp + + return col + +def trace_to_light(scene, ray, light_dist): + col = scene.light.colour + for obj in scene.objs: + t = obj.intersect(ray) + if t < light_dist: + col *= obj.surface.transp + return col + +class Canvas: + def __init__(self, width, height): + self.width = width + self.height = height + self.data = bytearray(3 * width * height) + + def put_pix(self, x, y, c): + off = 3 * (y * self.width + x) + self.data[off] = min(255, max(0, int(255 * c.x))) + self.data[off + 1] = min(255, max(0, int(255 * c.y))) + self.data[off + 2] = min(255, max(0, int(255 * c.z))) + + def write_ppm(self, filename): + with open(filename, 'wb') as f: + f.write(bytes('P6 %d %d 255\n' % (self.width, self.height), 'ascii')) + f.write(self.data) + +def main(w, h, d): + canvas = Canvas(w, h) + view = View(32, 32, 64, Vec(0, 0, 50), Vec(1, 0, 0), Vec(0, 1, 0), Vec(0, 0, -1)) + scene = Scene( + 0.5, + Light(Vec(0, 8, 0), RGB(1, 1, 1), True), + [ + Plane(Surface.dull(RGB(1, 0, 0)), Vec(-10, 0, 0), Vec(1, 0, 0)), + Plane(Surface.dull(RGB(0, 1, 0)), Vec(10, 0, 0), Vec(-1, 0, 0)), + Plane(Surface.dull(RGB(1, 1, 1)), Vec(0, 0, -10), Vec(0, 0, 1)), + Plane(Surface.dull(RGB(1, 1, 1)), Vec(0, -10, 0), Vec(0, 1, 0)), + Plane(Surface.dull(RGB(1, 1, 1)), Vec(0, 10, 0), Vec(0, -1, 0)), + Sphere(Surface.shiny(RGB(1, 1, 1)), Vec(-5, -4, 3), 4), + Sphere(Surface.dull(RGB(0, 0, 1)), Vec(4, -5, 0), 4), + Sphere(Surface.transparent(RGB(0.2, 0.2, 0.2)), Vec(6, -1, 8), 4), + ] + ) + trace_scene(canvas, view, scene, d) + return canvas + +# For testing +#main(256, 256, 4).write_ppm('rt.ppm') + +########################################################################### +# Benchmark interface + +bm_params = { + (100, 100): (5, 5, 2), + (1000, 100): (18, 18, 3), + (5000, 100): (40, 40, 3), +} + +def bm_setup(params): + return lambda: main(*params), lambda: (params[0] * params[1] * params[2], None) From 73fccf59672c7087d6290bb036fe5c72899086b6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 26 Jun 2019 14:27:32 +1000 Subject: [PATCH 0197/1299] tests/perf_bench: Add some viper performance benchmarks. To test raw viper function call overhead: function entry, exit and conversion of arguments to/from objects. --- tests/perf_bench/viper_call0.py | 19 +++++++++++++++++++ tests/perf_bench/viper_call1a.py | 19 +++++++++++++++++++ tests/perf_bench/viper_call1b.py | 19 +++++++++++++++++++ tests/perf_bench/viper_call1c.py | 19 +++++++++++++++++++ tests/perf_bench/viper_call2a.py | 19 +++++++++++++++++++ tests/perf_bench/viper_call2b.py | 19 +++++++++++++++++++ 6 files changed, 114 insertions(+) create mode 100644 tests/perf_bench/viper_call0.py create mode 100644 tests/perf_bench/viper_call1a.py create mode 100644 tests/perf_bench/viper_call1b.py create mode 100644 tests/perf_bench/viper_call1c.py create mode 100644 tests/perf_bench/viper_call2a.py create mode 100644 tests/perf_bench/viper_call2b.py diff --git a/tests/perf_bench/viper_call0.py b/tests/perf_bench/viper_call0.py new file mode 100644 index 0000000000000..0f476b127bce5 --- /dev/null +++ b/tests/perf_bench/viper_call0.py @@ -0,0 +1,19 @@ +@micropython.viper +def f0(): + pass + +@micropython.native +def call(r): + f = f0 + for _ in r: + f() + +bm_params = { + (50, 10): (15000,), + (100, 10): (30000,), + (1000, 10): (300000,), + (5000, 10): (1500000,), +} + +def bm_setup(params): + return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) diff --git a/tests/perf_bench/viper_call1a.py b/tests/perf_bench/viper_call1a.py new file mode 100644 index 0000000000000..2bb4a28fd30b9 --- /dev/null +++ b/tests/perf_bench/viper_call1a.py @@ -0,0 +1,19 @@ +@micropython.viper +def f1a(x): + return x + +@micropython.native +def call(r): + f = f1a + for _ in r: + f(1) + +bm_params = { + (50, 10): (15000,), + (100, 10): (30000,), + (1000, 10): (300000,), + (5000, 10): (1500000,), +} + +def bm_setup(params): + return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) diff --git a/tests/perf_bench/viper_call1b.py b/tests/perf_bench/viper_call1b.py new file mode 100644 index 0000000000000..cda64007fedde --- /dev/null +++ b/tests/perf_bench/viper_call1b.py @@ -0,0 +1,19 @@ +@micropython.viper +def f1b(x) -> int: + return int(x) + +@micropython.native +def call(r): + f = f1b + for _ in r: + f(1) + +bm_params = { + (50, 10): (15000,), + (100, 10): (30000,), + (1000, 10): (300000,), + (5000, 10): (1500000,), +} + +def bm_setup(params): + return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) diff --git a/tests/perf_bench/viper_call1c.py b/tests/perf_bench/viper_call1c.py new file mode 100644 index 0000000000000..c653eb8d3ee18 --- /dev/null +++ b/tests/perf_bench/viper_call1c.py @@ -0,0 +1,19 @@ +@micropython.viper +def f1c(x:int) -> int: + return x + +@micropython.native +def call(r): + f = f1c + for _ in r: + f(1) + +bm_params = { + (50, 10): (15000,), + (100, 10): (30000,), + (1000, 10): (300000,), + (5000, 10): (1500000,), +} + +def bm_setup(params): + return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) diff --git a/tests/perf_bench/viper_call2a.py b/tests/perf_bench/viper_call2a.py new file mode 100644 index 0000000000000..6204f985f9f20 --- /dev/null +++ b/tests/perf_bench/viper_call2a.py @@ -0,0 +1,19 @@ +@micropython.viper +def f2a(x, y): + return x + +@micropython.native +def call(r): + f = f2a + for _ in r: + f(1, 2) + +bm_params = { + (50, 10): (15000,), + (100, 10): (30000,), + (1000, 10): (300000,), + (5000, 10): (1500000,), +} + +def bm_setup(params): + return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) diff --git a/tests/perf_bench/viper_call2b.py b/tests/perf_bench/viper_call2b.py new file mode 100644 index 0000000000000..087cf8ab0cd30 --- /dev/null +++ b/tests/perf_bench/viper_call2b.py @@ -0,0 +1,19 @@ +@micropython.viper +def f2b(x:int, y:int) -> int: + return x + y + +@micropython.native +def call(r): + f = f2b + for _ in r: + f(1, 2) + +bm_params = { + (50, 10): (15000,), + (100, 10): (30000,), + (1000, 10): (300000,), + (5000, 10): (1500000,), +} + +def bm_setup(params): + return lambda: call(range(params[0])), lambda: (params[0] // 1000, None) From 9cebead27600f86a73f3326b455dcfcb065afe5f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 26 Jun 2019 14:29:06 +1000 Subject: [PATCH 0198/1299] travis: Enable performance benchmark tests on standard unix build. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b71cabcc808bd..9fbdb1698eb88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,6 +89,7 @@ jobs: - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix - make ${MAKEOPTS} -C ports/unix test + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython ./run-perfbench.py 1000 1000) # unix nanbox - stage: test From 378659209778a1bde24e9b15793087023b02bbd9 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 13 May 2019 00:13:59 +1000 Subject: [PATCH 0199/1299] stm32/boards: Optimise flash and RAM allocation for L4 boards. Optimisations are: - Remove FLASH_ISR section since devices with a small flash sector erase size don't need special FLASH_ISR handling. This reduces flash image by approx 1.5k. - Make SRAM2 contiguous with SRAM1 where possible. - Simplify configuration of 2k RAM buffer used for flash filesystem. RAM changes with this commit: - L432: stack 6k -> 10k, bss + heap 42k -> 52k - L476: stack 16k -> 30k, bss + heap 80k -> 96k - L496: stack 206k -> 16k, bss + heap 112k -> 302k --- .../boards/B_L475E_IOT01A/mpconfigboard.mk | 6 ++-- ports/stm32/boards/LIMIFROG/mpconfigboard.mk | 4 +-- .../boards/NUCLEO_L476RG/mpconfigboard.mk | 5 ++-- .../boards/STM32L476DISC/mpconfigboard.mk | 4 +-- .../boards/STM32L496GDISC/mpconfigboard.mk | 4 +-- ports/stm32/boards/stm32l432.ld | 25 ++++++++++------ ports/stm32/boards/stm32l476xe.ld | 24 +++++++-------- ports/stm32/boards/stm32l476xg.ld | 24 +++++++-------- ports/stm32/boards/stm32l496xg.ld | 29 +++++++++---------- 9 files changed, 61 insertions(+), 64 deletions(-) diff --git a/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.mk b/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.mk index 55e443e919ac0..137b6be23d01a 100644 --- a/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.mk +++ b/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.mk @@ -1,9 +1,7 @@ MCU_SERIES = l4 CMSIS_MCU = STM32L475xx # The stm32l475 does not have a LDC controller which is -# the only diffrence to the stm32l476 - so reuse some files. +# the only difference to the stm32l476 - so reuse some files. AF_FILE = boards/stm32l476_af.csv -LD_FILES = boards/stm32l476xg.ld boards/common_ifs.ld -TEXT0_ADDR = 0x08000000 -TEXT1_ADDR = 0x08004000 +LD_FILES = boards/stm32l476xg.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg diff --git a/ports/stm32/boards/LIMIFROG/mpconfigboard.mk b/ports/stm32/boards/LIMIFROG/mpconfigboard.mk index 2adc98f0b1c90..ef1ec93b0b563 100644 --- a/ports/stm32/boards/LIMIFROG/mpconfigboard.mk +++ b/ports/stm32/boards/LIMIFROG/mpconfigboard.mk @@ -1,6 +1,4 @@ MCU_SERIES = l4 CMSIS_MCU = STM32L476xx AF_FILE = boards/stm32l476_af.csv -LD_FILES = boards/stm32l476xe.ld boards/common_ifs.ld -TEXT0_ADDR = 0x08000000 -TEXT1_ADDR = 0x08004000 +LD_FILES = boards/stm32l476xe.ld boards/common_basic.ld diff --git a/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.mk index 38ae5af212cfa..10c69461c9309 100644 --- a/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.mk @@ -1,6 +1,5 @@ MCU_SERIES = l4 CMSIS_MCU = STM32L476xx AF_FILE = boards/stm32l476_af.csv -LD_FILES = boards/stm32l476xg.ld boards/common_ifs.ld -TEXT0_ADDR = 0x08000000 -TEXT1_ADDR = 0x08004000 +LD_FILES = boards/stm32l476xg.ld boards/common_basic.ld +OPENOCD_CONFIG = boards/openocd_stm32l4.cfg diff --git a/ports/stm32/boards/STM32L476DISC/mpconfigboard.mk b/ports/stm32/boards/STM32L476DISC/mpconfigboard.mk index 2cad9e2e566fe..10c69461c9309 100644 --- a/ports/stm32/boards/STM32L476DISC/mpconfigboard.mk +++ b/ports/stm32/boards/STM32L476DISC/mpconfigboard.mk @@ -1,7 +1,5 @@ MCU_SERIES = l4 CMSIS_MCU = STM32L476xx AF_FILE = boards/stm32l476_af.csv -LD_FILES = boards/stm32l476xg.ld boards/common_ifs.ld -TEXT0_ADDR = 0x08000000 -TEXT1_ADDR = 0x08004000 +LD_FILES = boards/stm32l476xg.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg diff --git a/ports/stm32/boards/STM32L496GDISC/mpconfigboard.mk b/ports/stm32/boards/STM32L496GDISC/mpconfigboard.mk index 3a617465563b0..a85635e306d91 100644 --- a/ports/stm32/boards/STM32L496GDISC/mpconfigboard.mk +++ b/ports/stm32/boards/STM32L496GDISC/mpconfigboard.mk @@ -1,7 +1,5 @@ MCU_SERIES = l4 CMSIS_MCU = STM32L496xx AF_FILE = boards/stm32l496_af.csv -LD_FILES = boards/stm32l496xg.ld boards/common_ifs.ld -TEXT0_ADDR = 0x08000000 -TEXT1_ADDR = 0x08004000 +LD_FILES = boards/stm32l496xg.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg diff --git a/ports/stm32/boards/stm32l432.ld b/ports/stm32/boards/stm32l432.ld index 5558b13c89334..4699543d66912 100644 --- a/ports/stm32/boards/stm32l432.ld +++ b/ports/stm32/boards/stm32l432.ld @@ -5,23 +5,30 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K - FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 256K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K - SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 16K + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 230K /* sectors 0-114 */ + FLASH_FS (r) : ORIGIN = 0x08060000, LENGTH = 26K /* sectors 115-127 */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* SRAM1, 48K + SRAM2, 16K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the stack. The stack is full descending so begins just above last byte - of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; -_sstack = _estack - 6K; /* tunable */ +/* Define the stack. The stack is full descending so begins just above last byte of RAM, + or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_ram_fs_cache_end = _ram_end; +_ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ + +_estack = _ram_fs_cache_start - _estack_reserve; +_sstack = _estack - 10K; /* stack = 10K */ + _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _sstack; +_heap_end = _sstack; /* bss + heap = 52K, tunable by adjusting stack size */ + +_flash_fs_start = ORIGIN(FLASH_FS); +_flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32l476xe.ld b/ports/stm32/boards/stm32l476xe.ld index e4bcda1f16f12..6eaf71545d0a1 100644 --- a/ports/stm32/boards/stm32l476xe.ld +++ b/ports/stm32/boards/stm32l476xe.ld @@ -5,31 +5,31 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K - FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sectors 0-7 */ - FLASH_TEXT (rx) : ORIGIN = 0x08004000, LENGTH = 368K /* sectors 8-191 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K /* sectors 0-191 */ FLASH_FS (r) : ORIGIN = 0x08060000, LENGTH = 128K /* sectors 192-255 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K - SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K - FS_CACHE(xrw) : ORIGIN = 0x10007800, LENGTH = 2K + SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K /* not contiguous with RAM */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the stack. The stack is full descending so begins just above last byte - of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; -_sstack = _estack - 16K; /* tunable */ +/* Define the stack. The stack is full descending so begins just above last byte of RAM, + or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ -_ram_fs_cache_start = ORIGIN(FS_CACHE); -_ram_fs_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_ram_fs_cache_end = ORIGIN(SRAM2) + LENGTH(SRAM2); /* fs_cache in SRAM2 */ +_ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ + +_estack = _ram_fs_cache_start - _estack_reserve; /* stack in SRAM2 */ +_sstack = ORIGIN(SRAM2); /* stack = 30K */ + _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _sstack; +_heap_end = _ram_end; /* bss + heap = 96K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32l476xg.ld b/ports/stm32/boards/stm32l476xg.ld index 9fe83c74a4a47..09c3f29c54999 100644 --- a/ports/stm32/boards/stm32l476xg.ld +++ b/ports/stm32/boards/stm32l476xg.ld @@ -5,31 +5,31 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K - FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sectors 0-7 */ - FLASH_TEXT (rx) : ORIGIN = 0x08004000, LENGTH = 496K /* sectors 8-255 */ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* sectors 0-255 */ FLASH_FS (r) : ORIGIN = 0x08080000, LENGTH = 512K /* sectors 256-511 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K - SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K - FS_CACHE(xrw) : ORIGIN = 0x10007800, LENGTH = 2K + SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 32K /* not contiguous with RAM */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the stack. The stack is full descending so begins just above last byte - of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; -_sstack = _estack - 16K; /* tunable */ +/* Define the stack. The stack is full descending so begins just above last byte of RAM, + or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ -_ram_fs_cache_start = ORIGIN(FS_CACHE); -_ram_fs_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); _ram_start = ORIGIN(RAM); _ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_ram_fs_cache_end = ORIGIN(SRAM2) + LENGTH(SRAM2); /* fs_cache in SRAM2 */ +_ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ + +_estack = _ram_fs_cache_start - _estack_reserve; /* stack in SRAM2 */ +_sstack = ORIGIN(SRAM2); /* stack = 30K */ + _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _sstack; +_heap_end = _ram_end; /* bss + heap = 96K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32l496xg.ld b/ports/stm32/boards/stm32l496xg.ld index c3399034220ec..327cb5ce13407 100644 --- a/ports/stm32/boards/stm32l496xg.ld +++ b/ports/stm32/boards/stm32l496xg.ld @@ -5,31 +5,30 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K - FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sectors 0-7 */ - FLASH_TEXT (rx) : ORIGIN = 0x08004000, LENGTH = 596K /* sectors 8-305 */ - FLASH_FS (r) : ORIGIN = 0x08099000, LENGTH = 412K /* sectors 306-511 412 KiB */ - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K - SRAM2 (xrw) : ORIGIN = 0x20040000, LENGTH = 62K /* leave 2K for flash fs cache */ - FS_CACHE(xrw) : ORIGIN = 0x2004f800, LENGTH = 2K + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 612K /* sectors 0-305 */ + FLASH_FS (r) : ORIGIN = 0x08099000, LENGTH = 412K /* sectors 306-511 412 KiB */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K /* SRAM1, 256K + SRAM2, 64K */ } /* produce a link error if there is not this amount of RAM for these sections */ _minimum_stack_size = 2K; _minimum_heap_size = 16K; -/* Define the stack. The stack is full descending so begins just above last byte - of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */ -_estack = ORIGIN(RAM) + LENGTH(RAM) + LENGTH(SRAM2) - _estack_reserve; -_sstack = _estack - 206K; /* tunable */ +/* Define the stack. The stack is full descending so begins just above last byte of RAM, + or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ /* RAM extents for the garbage collector */ -_ram_fs_cache_start = ORIGIN(FS_CACHE); -_ram_fs_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE); _ram_start = ORIGIN(RAM); -_ram_end = ORIGIN(RAM) + LENGTH(RAM) + LENGTH(SRAM2); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_ram_fs_cache_end = _ram_end; +_ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ + +_estack = _ram_fs_cache_start - _estack_reserve; +_sstack = _estack - 16K; /* stack = 16K */ + _heap_start = _ebss; /* heap starts just after statically allocated memory */ -_heap_end = _sstack; +_heap_end = _sstack; /* bss + heap = 302K, tunable by adjusting stack size */ _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); From b7da67cdaaf32317cfc9a3940bd58f2aab4976c9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 19 Jun 2019 14:02:08 +1000 Subject: [PATCH 0200/1299] lib/utils/sys_stdio_mphal: Add support to poll sys.stdin and sys.stdout. A port must provide the following function for this to work: uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags); --- lib/utils/sys_stdio_mphal.c | 14 +++++++++++++- py/mphal.h | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/utils/sys_stdio_mphal.c b/lib/utils/sys_stdio_mphal.c index 234db0829bf60..3fcaf8e5982d6 100644 --- a/lib/utils/sys_stdio_mphal.c +++ b/lib/utils/sys_stdio_mphal.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -85,6 +85,16 @@ STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, } } +STATIC mp_uint_t stdio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + (void)self_in; + if (request == MP_STREAM_POLL) { + return mp_hal_stdio_poll(arg); + } else { + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } +} + STATIC mp_obj_t stdio_obj___exit__(size_t n_args, const mp_obj_t *args) { return mp_const_none; } @@ -112,6 +122,7 @@ STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table); STATIC const mp_stream_p_t stdio_obj_stream_p = { .read = stdio_read, .write = stdio_write, + .ioctl = stdio_ioctl, .is_text = true, }; @@ -146,6 +157,7 @@ STATIC mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = { .read = stdio_buffer_read, .write = stdio_buffer_write, + .ioctl = stdio_ioctl, .is_text = false, }; diff --git a/py/mphal.h b/py/mphal.h index 92de01d08b913..66d80705a60ee 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -34,6 +34,10 @@ #include #endif +#ifndef mp_hal_stdio_poll +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags); +#endif + #ifndef mp_hal_stdin_rx_chr int mp_hal_stdin_rx_chr(void); #endif From 964ae328cd00260d9a017a4e67909694fded9902 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 24 Jun 2019 16:20:33 +1000 Subject: [PATCH 0201/1299] extmod/uos_dupterm: Add mp_uos_dupterm_poll to poll all dupterms. --- extmod/misc.h | 1 + extmod/uos_dupterm.c | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/extmod/misc.h b/extmod/misc.h index dae6bec4a10fc..40b091e5f73d5 100644 --- a/extmod/misc.h +++ b/extmod/misc.h @@ -36,6 +36,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj); #if MICROPY_PY_OS_DUPTERM bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream); +uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags); int mp_uos_dupterm_rx_chr(void); void mp_uos_dupterm_tx_strn(const char *str, size_t len); void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc); diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c index 42cb21444b010..9a8f0af4ed245 100644 --- a/extmod/uos_dupterm.c +++ b/extmod/uos_dupterm.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky - * Copyright (c) 2017 Damien P. George + * Copyright (c) 2017-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -53,6 +53,45 @@ void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) { } } +uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags) { + uintptr_t poll_flags_out = 0; + + for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { + mp_obj_t s = MP_STATE_VM(dupterm_objs[idx]); + if (s == MP_OBJ_NULL) { + continue; + } + + int errcode = 0; + mp_uint_t ret = 0; + const mp_stream_p_t *stream_p = mp_get_stream(s); + #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM + if (mp_uos_dupterm_is_builtin_stream(s)) { + ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode); + } else + #endif + { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode); + nlr_pop(); + } else { + // Ignore error with ioctl + } + } + + if (ret != MP_STREAM_ERROR) { + poll_flags_out |= ret; + if (poll_flags_out == poll_flags) { + // Finish early if all requested flags are set + break; + } + } + } + + return poll_flags_out; +} + int mp_uos_dupterm_rx_chr(void) { for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) { From c80614dfc8b6454819380e4886d49dfd93193691 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 19 Jun 2019 14:02:38 +1000 Subject: [PATCH 0202/1299] ports: Provide mp_hal_stdio_poll for sys.stdio polling where needed. --- ports/cc3200/hal/cc3200_hal.h | 1 + ports/esp32/mphalport.c | 9 +++++++++ ports/esp8266/esp_mphal.c | 9 +++++++++ ports/pic16bit/pic16bit_mphal.c | 9 +++++++++ ports/stm32/mphalport.c | 11 +++++++++++ ports/teensy/teensy_hal.c | 14 ++++++++++++++ 6 files changed, 53 insertions(+) diff --git a/ports/cc3200/hal/cc3200_hal.h b/ports/cc3200/hal/cc3200_hal.h index 71e245eeb1c5d..3d0d632d519b4 100644 --- a/ports/cc3200/hal/cc3200_hal.h +++ b/ports/cc3200/hal/cc3200_hal.h @@ -64,5 +64,6 @@ extern void HAL_SystemDeInit (void); extern void HAL_IncrementTick(void); extern void mp_hal_set_interrupt_char (int c); +#define mp_hal_stdio_poll(poll_flags) (0) // not implemented #define mp_hal_delay_us(usec) UtilsDelay(UTILS_DELAY_US_TO_COUNT(usec)) #define mp_hal_ticks_cpu() (SysTickPeriodGet() - SysTickValueGet()) diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index 804c719869ef8..0d1ea74d6b342 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -34,6 +34,7 @@ #include "rom/uart.h" #include "py/obj.h" +#include "py/stream.h" #include "py/mpstate.h" #include "py/mphal.h" #include "extmod/misc.h" @@ -45,6 +46,14 @@ TaskHandle_t mp_main_task_handle; STATIC uint8_t stdin_ringbuf_array[256]; ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array)}; +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { + ret |= MP_STREAM_POLL_RD; + } + return ret; +} + int mp_hal_stdin_rx_chr(void) { for (;;) { int c = ringbuf_get(&stdin_ringbuf); diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c index 351bf522c8295..2ce288ea3f0fb 100644 --- a/ports/esp8266/esp_mphal.c +++ b/ports/esp8266/esp_mphal.c @@ -32,6 +32,7 @@ #include "user_interface.h" #include "ets_alt_task.h" #include "py/runtime.h" +#include "py/stream.h" #include "extmod/misc.h" #include "lib/utils/pyexec.h" @@ -56,6 +57,14 @@ void mp_hal_delay_us(uint32_t us) { } } +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { + ret |= MP_STREAM_POLL_RD; + } + return ret; +} + int mp_hal_stdin_rx_chr(void) { for (;;) { int c = ringbuf_get(&stdin_ringbuf); diff --git a/ports/pic16bit/pic16bit_mphal.c b/ports/pic16bit/pic16bit_mphal.c index 35955f2d3ee57..adab3819348bc 100644 --- a/ports/pic16bit/pic16bit_mphal.c +++ b/ports/pic16bit/pic16bit_mphal.c @@ -25,6 +25,7 @@ */ #include +#include "py/stream.h" #include "py/mphal.h" #include "board.h" @@ -51,6 +52,14 @@ void mp_hal_set_interrupt_char(int c) { interrupt_char = c; } +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if ((poll_flags & MP_STREAM_POLL_RD) && uart_rx_any()) { + ret |= MP_STREAM_POLL_RD; + } + return ret; +} + int mp_hal_stdin_rx_chr(void) { for (;;) { if (uart_rx_any()) { diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index f4ae7293c80a9..79b28bd3defcc 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -1,6 +1,7 @@ #include #include "py/runtime.h" +#include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "extmod/misc.h" @@ -19,6 +20,16 @@ NORETURN void mp_hal_raise(HAL_StatusTypeDef status) { mp_raise_OSError(mp_hal_status_to_errno_table[status]); } +MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { + int errcode; + const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_PORT(pyb_stdio_uart)); + ret = stream_p->ioctl(MP_STATE_PORT(pyb_stdio_uart), MP_STREAM_POLL, poll_flags, &errcode); + } + return ret | mp_uos_dupterm_poll(poll_flags); +} + MP_WEAK int mp_hal_stdin_rx_chr(void) { for (;;) { #if 0 diff --git a/ports/teensy/teensy_hal.c b/ports/teensy/teensy_hal.c index 7ce82f1d2a778..e9cc6778d576a 100644 --- a/ports/teensy/teensy_hal.c +++ b/ports/teensy/teensy_hal.c @@ -2,6 +2,7 @@ #include #include "py/runtime.h" +#include "py/stream.h" #include "py/mphal.h" #include "usb.h" #include "uart.h" @@ -21,6 +22,19 @@ void mp_hal_set_interrupt_char(int c) { // you can't press Control-C and get your python script to stop. } +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if (poll_flags & MP_STREAM_POLL_RD) { + if (usb_vcp_rx_num()) { + ret |= MP_STREAM_POLL_RD; + } + if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) { + ret |= MP_STREAM_POLL_RD; + } + } + return ret; +} + int mp_hal_stdin_rx_chr(void) { for (;;) { byte c; From 875af757bd248dab636f06efd359f61ca91baeaa Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 22 Jun 2019 23:00:34 +1000 Subject: [PATCH 0203/1299] lib: Add asf4 as a submodule. --- .gitmodules | 3 +++ lib/asf4 | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/asf4 diff --git a/.gitmodules b/.gitmodules index 216a3b909c31c..25e7077cde5c5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,3 +21,6 @@ [submodule "lib/mbedtls"] path = lib/mbedtls url = https://github.com/ARMmbed/mbedtls.git +[submodule "lib/asf4"] + path = lib/asf4 + url = https://github.com/adafruit/asf4 diff --git a/lib/asf4 b/lib/asf4 new file mode 160000 index 0000000000000..d270f79aa16dd --- /dev/null +++ b/lib/asf4 @@ -0,0 +1 @@ +Subproject commit d270f79aa16dd8fd4ae3b6c14544283dcb992e9c From 258d10862df43c5a90ce8893ec44a627b155dd19 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 22 Jun 2019 23:01:31 +1000 Subject: [PATCH 0204/1299] lib: Add tinyusb as a submodule. --- .gitmodules | 3 +++ lib/tinyusb | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/tinyusb diff --git a/.gitmodules b/.gitmodules index 25e7077cde5c5..544815b3a3468 100644 --- a/.gitmodules +++ b/.gitmodules @@ -24,3 +24,6 @@ [submodule "lib/asf4"] path = lib/asf4 url = https://github.com/adafruit/asf4 +[submodule "lib/tinyusb"] + path = lib/tinyusb + url = https://github.com/hathach/tinyusb diff --git a/lib/tinyusb b/lib/tinyusb new file mode 160000 index 0000000000000..393492823ce03 --- /dev/null +++ b/lib/tinyusb @@ -0,0 +1 @@ +Subproject commit 393492823ce037a2e46d367d61fad1235859af2e From f073f2b543683eeab6573b01b9152800660cd5cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 22 Jun 2019 23:01:55 +1000 Subject: [PATCH 0205/1299] tools: Add uf2conv.py from Microsoft/uf2 repository. Repository https://github.com/Microsoft/uf2 commit 19615407727073e36d81bf239c52108ba92e7660 --- tools/uf2conv.py | 319 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100755 tools/uf2conv.py diff --git a/tools/uf2conv.py b/tools/uf2conv.py new file mode 100755 index 0000000000000..2f2812abf978c --- /dev/null +++ b/tools/uf2conv.py @@ -0,0 +1,319 @@ +#!/usr/bin/env python3 + +# Microsoft UF2 +# +# The MIT License (MIT) +# +# Copyright (c) Microsoft Corporation +# +# All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import struct +import subprocess +import re +import os +import os.path +import argparse + + +UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" +UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected +UF2_MAGIC_END = 0x0AB16F30 # Ditto + +families = { + 'SAMD21': 0x68ed2b88, + 'SAMD51': 0x55114460, + 'NRF52': 0x1b57745f, + 'STM32F1': 0x5ee21072, + 'STM32F4': 0x57755a57, + 'ATMEGA32': 0x16573617, +} + +INFO_FILE = "/INFO_UF2.TXT" + +appstartaddr = 0x2000 +familyid = 0x0 + + +def is_uf2(buf): + w = struct.unpack(" 476: + assert False, "Invalid UF2 data size at " + ptr + newaddr = hd[3] + if curraddr == None: + appstartaddr = newaddr + curraddr = newaddr + padding = newaddr - curraddr + if padding < 0: + assert False, "Block out of order at " + ptr + if padding > 10*1024*1024: + assert False, "More than 10M of padding needed at " + ptr + if padding % 4 != 0: + assert False, "Non-word padding size at " + ptr + while padding > 0: + padding -= 4 + outp += b"\x00\x00\x00\x00" + outp += block[32 : 32 + datalen] + curraddr = newaddr + datalen + return outp + +def convert_to_carray(file_content): + outp = "const unsigned char bindata[] __attribute__((aligned(16))) = {" + for i in range(len(file_content)): + if i % 16 == 0: + outp += "\n" + outp += "0x%02x, " % ord(file_content[i]) + outp += "\n};\n" + return outp + +def convert_to_uf2(file_content): + global familyid + datapadding = b"" + while len(datapadding) < 512 - 256 - 32 - 4: + datapadding += b"\x00\x00\x00\x00" + numblocks = (len(file_content) + 255) // 256 + outp = b"" + for blockno in range(numblocks): + ptr = 256 * blockno + chunk = file_content[ptr:ptr + 256] + flags = 0x0 + if familyid: + flags |= 0x2000 + hd = struct.pack(b"= 3 and words[1] == "2" and words[2] == "FAT": + drives.append(words[0]) + else: + rootpath = "/media" + if sys.platform == "darwin": + rootpath = "/Volumes" + elif sys.platform == "linux": + tmp = rootpath + "/" + os.environ["USER"] + if os.path.isdir(tmp): + rootpath = tmp + for d in os.listdir(rootpath): + drives.append(os.path.join(rootpath, d)) + + + def has_info(d): + try: + return os.path.isfile(d + INFO_FILE) + except: + return False + + return list(filter(has_info, drives)) + + +def board_id(path): + with open(path + INFO_FILE, mode='r') as file: + file_content = file.read() + return re.search("Board-ID: ([^\r\n]*)", file_content).group(1) + + +def list_drives(): + for d in get_drives(): + print(d, board_id(d)) + + +def write_file(name, buf): + with open(name, "wb") as f: + f.write(buf) + print("Wrote %d bytes to %s." % (len(buf), name)) + + +def main(): + global appstartaddr, familyid + def error(msg): + print(msg) + sys.exit(1) + parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.') + parser.add_argument('input', metavar='INPUT', type=str, nargs='?', + help='input file (HEX, BIN or UF2)') + parser.add_argument('-b' , '--base', dest='base', type=str, + default="0x2000", + help='set base address of application for BIN format (default: 0x2000)') + parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, + help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible') + parser.add_argument('-d' , '--device', dest="device_path", + help='select a device path to flash') + parser.add_argument('-l' , '--list', action='store_true', + help='list connected devices') + parser.add_argument('-c' , '--convert', action='store_true', + help='do not flash, just convert') + parser.add_argument('-f' , '--family', dest='family', type=str, + default="0x0", + help='specify familyID - number or name (default: 0x0)') + parser.add_argument('-C' , '--carray', action='store_true', + help='convert binary file to a C array, not UF2') + args = parser.parse_args() + appstartaddr = int(args.base, 0) + + if args.family.upper() in families: + familyid = families[args.family.upper()] + else: + try: + familyid = int(args.family, 0) + except ValueError: + error("Family ID needs to be a number or one of: " + ", ".join(families.keys())) + + if args.list: + list_drives() + else: + if not args.input: + error("Need input file") + with open(args.input, mode='rb') as f: + inpbuf = f.read() + from_uf2 = is_uf2(inpbuf) + ext = "uf2" + if from_uf2: + outbuf = convert_from_uf2(inpbuf) + ext = "bin" + elif is_hex(inpbuf): + outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8")) + elif args.carray: + outbuf = convert_to_carray(inpbuf) + ext = "h" + else: + outbuf = convert_to_uf2(inpbuf) + print("Converting to %s, output size: %d, start address: 0x%x" % + (ext, len(outbuf), appstartaddr)) + if args.convert: + drives = [] + if args.output == None: + args.output = "flash." + ext + else: + drives = get_drives() + + if args.output: + write_file(args.output, outbuf) + else: + if len(drives) == 0: + error("No drive to deploy.") + for d in drives: + print("Flashing %s (%s)" % (d, board_id(d))) + write_file(d + "/NEW.UF2", outbuf) + + +if __name__ == "__main__": + main() From 5f9bd11527cfa9b643ccd75841f2faf9918457dd Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 22 Jun 2019 23:03:41 +1000 Subject: [PATCH 0206/1299] samd: Add new port to Microchip SAMDxx microcontrollers. Initially supporting SAMD21 and SAMD51. --- ports/samd/Makefile | 100 +++++++ ports/samd/README.md | 7 + .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk | 4 + .../ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld | 17 ++ .../mpconfigboard.h | 7 + .../samd/boards/ADAFRUIT_TRINKET_M0/board.mk | 4 + ports/samd/boards/ADAFRUIT_TRINKET_M0/link.ld | 17 ++ .../ADAFRUIT_TRINKET_M0/mpconfigboard.h | 2 + ports/samd/main.c | 98 +++++++ ports/samd/makefile | 12 + ports/samd/modmachine.c | 72 +++++ ports/samd/modutime.c | 47 ++++ ports/samd/mpconfigport.h | 109 ++++++++ ports/samd/mphalport.c | 112 ++++++++ ports/samd/mphalport.h | 39 +++ ports/samd/qstrdefsport.h | 1 + ports/samd/samd_isr.c | 252 ++++++++++++++++++ ports/samd/samd_soc.c | 152 +++++++++++ ports/samd/samd_soc.h | 53 ++++ ports/samd/sections.ld | 37 +++ ports/samd/tusb_config.h | 47 ++++ ports/samd/tusb_port.c | 146 ++++++++++ 22 files changed, 1335 insertions(+) create mode 100644 ports/samd/Makefile create mode 100644 ports/samd/README.md create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld create mode 100644 ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h create mode 100644 ports/samd/boards/ADAFRUIT_TRINKET_M0/board.mk create mode 100644 ports/samd/boards/ADAFRUIT_TRINKET_M0/link.ld create mode 100644 ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h create mode 100644 ports/samd/main.c create mode 100644 ports/samd/makefile create mode 100644 ports/samd/modmachine.c create mode 100644 ports/samd/modutime.c create mode 100644 ports/samd/mpconfigport.h create mode 100644 ports/samd/mphalport.c create mode 100644 ports/samd/mphalport.h create mode 100644 ports/samd/qstrdefsport.h create mode 100644 ports/samd/samd_isr.c create mode 100644 ports/samd/samd_soc.c create mode 100644 ports/samd/samd_soc.h create mode 100644 ports/samd/sections.ld create mode 100644 ports/samd/tusb_config.h create mode 100644 ports/samd/tusb_port.c diff --git a/ports/samd/Makefile b/ports/samd/Makefile new file mode 100644 index 0000000000000..f4a09ad7c10ec --- /dev/null +++ b/ports/samd/Makefile @@ -0,0 +1,100 @@ +BOARD ?= ADAFRUIT_ITSYBITSY_M4_EXPRESS +BOARD_DIR ?= boards/$(BOARD) +BUILD ?= build-$(BOARD) + +CROSS_COMPILE ?= arm-none-eabi- +UF2CONV ?= $(TOP)/tools/uf2conv.py + +ifeq ($(wildcard $(BOARD_DIR)/.),) +$(error Invalid BOARD specified: $(BOARD_DIR)) +endif + +include ../../py/mkenv.mk +include $(BOARD_DIR)/board.mk + +# Qstr definitions (must come before including py.mk) +QSTR_DEFS = qstrdefsport.h +QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h + +# Include py core make definitions +include $(TOP)/py/py.mk + +INC += -I. +INC += -I$(TOP) +INC += -I$(BUILD) +INC += -I$(BOARD_DIR) +INC += -I$(TOP)/lib/cmsis/inc +INC += -I$(TOP)/lib/asf4/$(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]')/include +INC += -I$(TOP)/lib/tinyusb/src + +CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float +CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard +CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion +CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__ +LDFLAGS = -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref +LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) + +# Tune for Debugging or Optimization +ifeq ($(DEBUG),1) +CFLAGS += -O0 -ggdb +else +CFLAGS += -Os -DNDEBUG +LDFLAGS += --gc-sections +CFLAGS += -fdata-sections -ffunction-sections +endif + +SRC_C = \ + main.c \ + modutime.c \ + modmachine.c \ + mphalport.c \ + samd_isr.c \ + samd_soc.c \ + tusb_port.c \ + lib/libc/string0.c \ + lib/libm/ef_sqrt.c \ + lib/libm/fmodf.c \ + lib/libm/math.c \ + lib/libm/nearbyintf.c \ + lib/mp-readline/readline.c \ + lib/tinyusb/src/class/cdc/cdc_device.c \ + lib/tinyusb/src/common/tusb_fifo.c \ + lib/tinyusb/src/device/usbd.c \ + lib/tinyusb/src/device/usbd_control.c \ + lib/tinyusb/src/tusb.c \ + lib/utils/printf.c \ + lib/utils/pyexec.c \ + lib/utils/stdout_helpers.c \ + +ifeq ($(MCU_SERIES),SAMD21) +SRC_C += lib/tinyusb/src/portable/microchip/samd21/dcd_samd21.c +SRC_S = lib/utils/gchelper_m0.s +else +SRC_C += lib/tinyusb/src/portable/microchip/samd51/dcd_samd51.c +SRC_S = lib/utils/gchelper_m3.s +endif + +# List of sources for qstr extraction +SRC_QSTR += modutime.c modmachine.c + +OBJ += $(PY_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) + +# Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };" +$(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces + +all: $(BUILD)/firmware.uf2 + +$(BUILD)/firmware.elf: $(OBJ) + $(ECHO) "LINK $@" + $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) + $(Q)$(SIZE) $@ + +$(BUILD)/firmware.bin: $(BUILD)/firmware.elf + $(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $(BUILD)/firmware.bin + +$(BUILD)/firmware.uf2: $(BUILD)/firmware.bin + $(Q)$(PYTHON) $(UF2CONV) -b $(TEXT0) -c -o $@ $< + +include $(TOP)/py/mkrules.mk diff --git a/ports/samd/README.md b/ports/samd/README.md new file mode 100644 index 0000000000000..b2ff4023ece75 --- /dev/null +++ b/ports/samd/README.md @@ -0,0 +1,7 @@ +Port of MicroPython to Microchip SAMD MCUs +========================================== + +Supports SAMD21 and SAMD51. + +Features: +- REPL over USB VCP diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk new file mode 100644 index 0000000000000..8cbd1885e464f --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk @@ -0,0 +1,4 @@ +MCU_SERIES = SAMD51 +CMSIS_MCU = SAMD51G19A +LD_FILES = $(BOARD_DIR)/link.ld sections.ld +TEXT0 = 0x4000 diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld new file mode 100644 index 0000000000000..e0baa9bba0281 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld @@ -0,0 +1,17 @@ +/* + GNU linker script for SAMD51 +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 512K - 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K +} + +/* Top end of the stack, with room for double-tap variable */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - 8; +_sstack = _estack - 16K; + +_sheap = _ebss; +_eheap = _sstack; diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h new file mode 100644 index 0000000000000..490704eadb178 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h @@ -0,0 +1,7 @@ +#define MICROPY_HW_BOARD_NAME "ItsyBitsy M4 Express" +#define MICROPY_HW_MCU_NAME "SAMD51G19A" + +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_PY_BUILTINS_COMPLEX (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_CMATH (0) diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.mk b/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.mk new file mode 100644 index 0000000000000..3955a4f7195fb --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.mk @@ -0,0 +1,4 @@ +MCU_SERIES = SAMD21 +CMSIS_MCU = SAMD21E18A +LD_FILES = $(BOARD_DIR)/link.ld sections.ld +TEXT0 = 0x2000 diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/link.ld b/ports/samd/boards/ADAFRUIT_TRINKET_M0/link.ld new file mode 100644 index 0000000000000..b7d59c315b643 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/link.ld @@ -0,0 +1,17 @@ +/* + GNU linker script for SAMD21 +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00002000, LENGTH = 256K - 8K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K +} + +/* Top end of the stack, with room for double-tap variable */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - 8; +_sstack = _estack - 8K; + +_sheap = _ebss; +_eheap = _sstack; diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h new file mode 100644 index 0000000000000..d3a6ba2d8687e --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "Trinket M0" +#define MICROPY_HW_MCU_NAME "SAMD21E18A" diff --git a/ports/samd/main.c b/ports/samd/main.c new file mode 100644 index 0000000000000..a66bdfbebd5ca --- /dev/null +++ b/ports/samd/main.c @@ -0,0 +1,98 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/compile.h" +#include "py/runtime.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/stackctrl.h" +#include "lib/utils/gchelper.h" +#include "lib/utils/pyexec.h" + +extern uint8_t _sstack, _estack, _sheap, _eheap; + +void samd_main(void) { + mp_stack_set_top(&_estack); + mp_stack_set_limit(&_estack - &_sstack - 1024); + + for (;;) { + gc_init(&_sheap, &_eheap); + mp_init(); + mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), 0); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); + mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); + + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } else { + if (pyexec_friendly_repl() != 0) { + break; + } + } + } + + mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); + gc_sweep_all(); + mp_deinit(); + } +} + +void gc_collect(void) { + gc_collect_start(); + uintptr_t regs[10]; + uintptr_t sp = gc_helper_get_regs_and_sp(regs); + gc_collect_root((void**)sp, ((uintptr_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); + gc_collect_end(); +} + +mp_lexer_t *mp_lexer_new_from_file(const char *filename) { + mp_raise_OSError(MP_ENOENT); +} + +mp_import_stat_t mp_import_stat(const char *path) { + return MP_IMPORT_STAT_NO_EXIST; +} + +mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); + +void nlr_jump_fail(void *val) { + for (;;) { + } +} + +#ifndef NDEBUG +void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { + mp_printf(MP_PYTHON_PRINTER, "Assertion '%s' failed, at file %s:%d\n", expr, file, line); + for(;;) { + } +} +#endif diff --git a/ports/samd/makefile b/ports/samd/makefile new file mode 100644 index 0000000000000..336d6f2800003 --- /dev/null +++ b/ports/samd/makefile @@ -0,0 +1,12 @@ +#BOARD = TRINKET +UF2DEV = /dev/sdb +#UF2CONV = /home/damien/others/uf2/utils/uf2conv.py + +include Makefile + +deploy: $(BUILD)/firmware.uf2 + $(ECHO) "Copying $< to the board" + mount $(UF2DEV) + cat /mnt/INFO_UF2.TXT > /dev/null + cp $< /mnt + umount /mnt diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c new file mode 100644 index 0000000000000..5362ef172c2b8 --- /dev/null +++ b/ports/samd/modmachine.c @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "extmod/machine_mem.h" +#include "samd_soc.h" + +#if defined(MCU_SAMD21) +#define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 32 * 1024 - 4)) +#elif defined(MCU_SAMD51) +#define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 192 * 1024 - 4)) +#endif +#define DBL_TAP_MAGIC_LOADER 0xf01669ef +#define DBL_TAP_MAGIC_RESET 0xf02669ef + +STATIC mp_obj_t machine_reset(void) { + *DBL_TAP_ADDR = DBL_TAP_MAGIC_RESET; + NVIC_SystemReset(); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); + +STATIC mp_obj_t machine_bootloader(void) { + *DBL_TAP_ADDR = DBL_TAP_MAGIC_LOADER; + NVIC_SystemReset(); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_bootloader_obj, machine_bootloader); + +STATIC mp_obj_t machine_freq(void) { + return MP_OBJ_NEW_SMALL_INT(CPU_FREQ); +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq); + +STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, + { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, + { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, + { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, + { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, + { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); + +const mp_obj_module_t mp_module_machine = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&machine_module_globals, +}; diff --git a/ports/samd/modutime.c b/ports/samd/modutime.c new file mode 100644 index 0000000000000..c3c152bb71f8f --- /dev/null +++ b/ports/samd/modutime.c @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "extmod/utime_mphal.h" + +STATIC const mp_rom_map_elem_t time_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, + + { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, + { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, + { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, + { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, + { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); + +const mp_obj_module_t mp_module_utime = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&time_module_globals, +}; diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h new file mode 100644 index 0000000000000..5b81d96b3ac82 --- /dev/null +++ b/ports/samd/mpconfigport.h @@ -0,0 +1,109 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Options controlling how MicroPython is built, overriding defaults in py/mpconfig.h + +// Board specific definitions +#include "mpconfigboard.h" + +// Memory allocation policies +#define MICROPY_GC_STACK_ENTRY_TYPE uint16_t +#define MICROPY_GC_ALLOC_THRESHOLD (0) +#define MICROPY_ALLOC_PARSE_CHUNK_INIT (32) +#define MICROPY_ALLOC_PATH_MAX (256) +#define MICROPY_QSTR_BYTES_IN_HASH (1) + +// Compiler configuration +#define MICROPY_COMP_CONST (0) + +// Python internal features +#define MICROPY_ENABLE_GC (1) +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_ENABLE_SOURCE_LINE (1) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) +#define MICROPY_CPYTHON_COMPAT (0) +#define MICROPY_CAN_OVERRIDE_BUILTINS (1) + +// Control over Python builtins +#define MICROPY_PY_ASYNC_AWAIT (0) +#define MICROPY_PY_BUILTINS_STR_COUNT (0) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_BUILTINS_SET (0) +#define MICROPY_PY_BUILTINS_FROZENSET (0) +#define MICROPY_PY_BUILTINS_PROPERTY (0) +#define MICROPY_PY_BUILTINS_ENUMERATE (0) +#define MICROPY_PY_BUILTINS_FILTER (0) +#define MICROPY_PY_BUILTINS_REVERSED (0) +#define MICROPY_PY_BUILTINS_MIN_MAX (0) +#define MICROPY_PY___FILE__ (0) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) +#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_PY_ATTRTUPLE (0) +#define MICROPY_PY_COLLECTIONS (0) +#define MICROPY_PY_SYS_MAXSIZE (1) + +// Extended modules +#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_MACHINE (1) + +// Hooks to add builtins + +#define MICROPY_PORT_BUILTINS \ + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, + +extern const struct _mp_obj_module_t mp_module_machine; +extern const struct _mp_obj_module_t mp_module_utime; + +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ + { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[8]; + +#define MP_STATE_PORT MP_STATE_VM + +// Miscellaneous settings + +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(void); \ + mp_handle_pending(); \ + __WFI(); \ + } while (0); + +#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) +#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) + +#define MP_SSIZE_MAX (0x7fffffff) +typedef int mp_int_t; // must be pointer size +typedef unsigned mp_uint_t; // must be pointer size +typedef long mp_off_t; + +// Need to provide a declaration/definition of alloca() +#include diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c new file mode 100644 index 0000000000000..9f3105c698c3b --- /dev/null +++ b/ports/samd/mphalport.c @@ -0,0 +1,112 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpstate.h" +#include "py/mphal.h" +#include "lib/utils/interrupt_char.h" +#include "samd_soc.h" +#include "tusb.h" + +#if MICROPY_KBD_EXCEPTION + +void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { + (void)itf; + (void)wanted_char; + tud_cdc_read_char(); // discard interrupt char + mp_keyboard_interrupt(); +} + +void mp_hal_set_interrupt_char(int c) { + if (c != -1) { + mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); + } + tud_cdc_set_wanted_char(c); +} + +void mp_keyboard_interrupt(void) { + MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); + #if MICROPY_ENABLE_SCHEDULER + if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { + MP_STATE_VM(sched_state) = MP_SCHED_PENDING; + } + #endif +} + +#endif + +void mp_hal_delay_ms(mp_uint_t ms) { + ms += 1; + uint32_t t0 = systick_ms; + while (systick_ms - t0 < ms) { + MICROPY_EVENT_POLL_HOOK + } +} + +void mp_hal_delay_us(mp_uint_t us) { + uint32_t ms = us / 1000 + 1; + uint32_t t0 = systick_ms; + while (systick_ms - t0 < ms) { + __WFI(); + } +} + +int mp_hal_stdin_rx_chr(void) { + for (;;) { + if (USARTx->USART.INTFLAG.bit.RXC) { + return USARTx->USART.DATA.bit.DATA; + } + if (tud_cdc_connected() && tud_cdc_available()) { + uint8_t buf[1]; + uint32_t count = tud_cdc_read(buf, sizeof(buf)); + if (count) { + return buf[0]; + } + } + __WFI(); + } +} + +void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + if (tud_cdc_connected()) { + for (size_t i = 0; i < len;) { + uint32_t n = len - i; + uint32_t n2 = tud_cdc_write(str + i, n); + if (n2 < n) { + while (!tud_cdc_write_flush()) { + __WFI(); + } + } + i += n2; + } + while (!tud_cdc_write_flush()) { + __WFI(); + } + } + while (len--) { + while (!(USARTx->USART.INTFLAG.bit.DRE)) { } + USARTx->USART.DATA.bit.DATA = *str++; + } +} diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h new file mode 100644 index 0000000000000..52562652e1ecf --- /dev/null +++ b/ports/samd/mphalport.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SAMD_MPHALPORT_H +#define MICROPY_INCLUDED_SAMD_MPHALPORT_H + +#include + +extern volatile uint32_t systick_ms; + +void mp_hal_set_interrupt_char(int c); + +static inline mp_uint_t mp_hal_ticks_ms(void) { return systick_ms; } +static inline mp_uint_t mp_hal_ticks_us(void) { return systick_ms * 1000; } +static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; } + +#endif // MICROPY_INCLUDED_SAMD_MPHALPORT_H diff --git a/ports/samd/qstrdefsport.h b/ports/samd/qstrdefsport.h new file mode 100644 index 0000000000000..3ba897069bf73 --- /dev/null +++ b/ports/samd/qstrdefsport.h @@ -0,0 +1 @@ +// qstrs specific to this port diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c new file mode 100644 index 0000000000000..8341df8c64f16 --- /dev/null +++ b/ports/samd/samd_isr.c @@ -0,0 +1,252 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "samd_soc.h" + +typedef void (*ISR)(void); + +extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; + +const ISR isr_vector[]; +uint32_t systick_ms; + +void Reset_Handler(void) __attribute__((naked)); +void Reset_Handler(void) { + // Set stack pointer + #if __CORTEX_M >= 0x03 + __asm volatile ("ldr sp, =_estack"); + #else + __asm volatile ("ldr r0, =_estack"); + __asm volatile ("mov sp, r0"); + #endif + // Copy .data section from flash to RAM + for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) { + *dest++ = *src++; + } + // Zero out .bss section + for (uint32_t *dest = &_sbss; dest < &_ebss;) { + *dest++ = 0; + } + + // When we get here: stack is initialised, bss is clear, data is copied + + #if __FPU_PRESENT == 1 && __FPU_USED == 1 + // Set CP10 and CP11 Full Access + SCB->CPACR |= (3UL << 10 * 2) | (3UL << 11 * 2); + #endif + + // SCB->VTOR + *((volatile uint32_t*)0xe000ed08) = (uint32_t)&isr_vector; + + // SCB->CCR: enable 8-byte stack alignment for IRQ handlers, in accord with EABI + *((volatile uint32_t*)0xe000ed14) |= 1 << 9; + + // Initialise the cpu and peripherals + samd_init(); + + // Now that we have a basic system up and running we can call main + samd_main(); + + // we must not return + for (;;) { + } +} + +void Default_Handler(void) { + for (;;) { + } +} + +void SysTick_Handler(void) { + systick_ms += 1; +} + +const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { + (ISR)&_estack, + &Reset_Handler, + &Default_Handler, // NMI_Handler + &Default_Handler, // HardFault_Handler + &Default_Handler, // MemManage_Handler + &Default_Handler, // BusFault_Handler + &Default_Handler, // UsageFault_Handler + 0, + 0, + 0, + 0, + &Default_Handler, // SVC_Handler + &Default_Handler, // DebugMon_Handler + 0, + &Default_Handler, // PendSV_Handler + &SysTick_Handler, // SysTick_Handler + 0, // line 0 + 0, + 0, + 0, + 0, + 0, + 0, + #if defined(MCU_SAMD21) + USB_Handler_wrapper, // line 7 + #else + 0, + #endif + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + #if defined(MCU_SAMD51) + &USB_0_Handler_wrapper, // line 80 + &USB_1_Handler_wrapper, + &USB_2_Handler_wrapper, + &USB_3_Handler_wrapper, + #else + 0, + 0, + 0, + 0, + #endif + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c new file mode 100644 index 0000000000000..569cd3802e8ad --- /dev/null +++ b/ports/samd/samd_soc.c @@ -0,0 +1,152 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "samd_soc.h" +#include "tusb.h" + +static void uart0_init(void) { + #if defined(MCU_SAMD21) + + // SERCOM0, TX=PA06=PAD2, RX=PA07=PAD3, ALT-D + PORT->Group[0].PMUX[3].reg = 0x33; + PORT->Group[0].PINCFG[6].reg = 1; + PORT->Group[0].PINCFG[7].reg = 1; + + PM->APBCMASK.bit.SERCOM0_ = 1; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_SERCOM0_CORE; + while (GCLK->STATUS.bit.SYNCBUSY) { } + + uint32_t rxpo = 3; + uint32_t txpo = 1; + + #elif defined(MCU_SAMD51) + + // SERCOM3, TX=PA17=PAD0, RX=PA16=PAD1, ALT-D + PORT->Group[0].PMUX[8].reg = 0x33; + PORT->Group[0].PINCFG[16].reg = 1; + PORT->Group[0].PINCFG[17].reg = 1; + + // Use Generator 0 which is already enabled and switched to DFLL @ 48MHz + GCLK->PCHCTRL[SERCOM3_GCLK_ID_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; + MCLK->APBBMASK.bit.SERCOM3_ = 1; + + uint32_t rxpo = 1; + uint32_t txpo = 2; + + #endif + + while (USARTx->USART.SYNCBUSY.bit.SWRST) { } + USARTx->USART.CTRLA.bit.SWRST = 1; + while (USARTx->USART.SYNCBUSY.bit.SWRST) { } + + USARTx->USART.CTRLA.reg = + SERCOM_USART_CTRLA_DORD + | SERCOM_USART_CTRLA_RXPO(rxpo) + | SERCOM_USART_CTRLA_TXPO(txpo) + | SERCOM_USART_CTRLA_MODE(1) + ; + USARTx->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN; + while (USARTx->USART.SYNCBUSY.bit.CTRLB) { } + #if CPU_FREQ == 8000000 + uint32_t baud = 50437; // 115200 baud; 65536*(1 - 16 * 115200/8e6) + #elif CPU_FREQ == 48000000 + uint32_t baud = 63019; // 115200 baud; 65536*(1 - 16 * 115200/48e6) + #elif CPU_FREQ == 120000000 + uint32_t baud = 64529; // 115200 baud; 65536*(1 - 16 * 115200/120e6) + #endif + USARTx->USART.BAUD.bit.BAUD = baud; + USARTx->USART.CTRLA.bit.ENABLE = 1; + while (USARTx->USART.SYNCBUSY.bit.ENABLE) { } +} + +static void usb_init(void) { + // Init USB clock + #if defined(MCU_SAMD21) + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_USB; + PM->AHBMASK.bit.USB_ = 1; + PM->APBBMASK.bit.USB_ = 1; + uint8_t alt = 6; // alt G, USB + #elif defined(MCU_SAMD51) + GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK1; + while (GCLK->PCHCTRL[USB_GCLK_ID].bit.CHEN == 0) { } + MCLK->AHBMASK.bit.USB_ = 1; + MCLK->APBBMASK.bit.USB_ = 1; + uint8_t alt = 7; // alt H, USB + #endif + + // Init USB pins + PORT->Group[0].DIRSET.reg = 1 << 25 | 1 << 24; + PORT->Group[0].OUTCLR.reg = 1 << 25 | 1 << 24; + PORT->Group[0].PMUX[12].reg = alt << 4 | alt; + PORT->Group[0].PINCFG[24].reg = PORT_PINCFG_PMUXEN; + PORT->Group[0].PINCFG[25].reg = PORT_PINCFG_PMUXEN; + + tusb_init(); +} + +void samd_init(void) { + #if defined(MCU_SAMD21) + + NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes" + NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz + + // Enable DFLL48M + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} + SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1) + | SYSCTRL_DFLLMUL_MUL(48000); + uint32_t coarse = (*((uint32_t*)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk) + >> FUSES_DFLL48M_COARSE_CAL_Pos; + if (coarse == 0x3f) { + coarse = 0x1f; + } + uint32_t fine = 512; + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(fine); + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM + | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE; + while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {} + + GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); + GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0); + while (GCLK->STATUS.bit.SYNCBUSY) { } + + // Configure PA10 as output for LED + PORT->Group[0].DIRSET.reg = 1 << 10; + + #elif defined(MCU_SAMD51) + + GCLK->GENCTRL[1].reg = 1 << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL; + while (GCLK->SYNCBUSY.bit.GENCTRL1) { } + + // Configure PA22 as output for LED + PORT->Group[0].DIRSET.reg = 1 << 22; + + #endif + + SysTick_Config(CPU_FREQ / 1000); + uart0_init(); + usb_init(); +} diff --git a/ports/samd/samd_soc.h b/ports/samd/samd_soc.h new file mode 100644 index 0000000000000..5f68610e4d0a3 --- /dev/null +++ b/ports/samd/samd_soc.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SAMD_SAMD_SOC_H +#define MICROPY_INCLUDED_SAMD_SAMD_SOC_H + +#include +#include "sam.h" + +#if defined(MCU_SAMD21) + +#define CPU_FREQ (48000000) +#define USARTx SERCOM0 + +#elif defined(MCU_SAMD51) + +#define CPU_FREQ (48000000) +#define USARTx SERCOM3 + +#endif + +void samd_init(void); +void samd_main(void); + +void USB_Handler_wrapper(void); +void USB_0_Handler_wrapper(void); +void USB_1_Handler_wrapper(void); +void USB_2_Handler_wrapper(void); +void USB_3_Handler_wrapper(void); + +#endif // MICROPY_INCLUDED_SAMD_SAMD_SOC_H diff --git a/ports/samd/sections.ld b/ports/samd/sections.ld new file mode 100644 index 0000000000000..cbcad463d0580 --- /dev/null +++ b/ports/samd/sections.ld @@ -0,0 +1,37 @@ +/* Define output sections */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + *(.text) + *(.text*) + *(.rodata) + *(.rodata*) + . = ALIGN(4); + _etext = .; + _sidata = _etext; + } >FLASH + + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + . = ALIGN(4); + _edata = .; + } >RAM + + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >RAM +} diff --git a/ports/samd/tusb_config.h b/ports/samd/tusb_config.h new file mode 100644 index 0000000000000..07fa680cbbb6b --- /dev/null +++ b/ports/samd/tusb_config.h @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SAMD_TUSB_CONFIG_H +#define MICROPY_INCLUDED_SAMD_TUSB_CONFIG_H + +// Common configuration + +#if defined(MCU_SAMD21) +#define CFG_TUSB_MCU OPT_MCU_SAMD21 +#elif defined(MCU_SAMD51) +#define CFG_TUSB_MCU OPT_MCU_SAMD51 +#endif +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#define CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) + +// Device configuration + +#define CFG_TUD_ENDOINT0_SIZE (64) +#define CFG_TUD_CDC (1) +#define CFG_TUD_CDC_RX_BUFSIZE (64) +#define CFG_TUD_CDC_TX_BUFSIZE (64) + +#endif // MICROPY_INCLUDED_SAMD_TUSB_CONFIG_H diff --git a/ports/samd/tusb_port.c b/ports/samd/tusb_port.c new file mode 100644 index 0000000000000..23c242b400169 --- /dev/null +++ b/ports/samd/tusb_port.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "samd_soc.h" +#include "tusb.h" + +#define USBD_VID (0xf055) +#define USBD_PID (0x9802) + +#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) +#define USBD_MAX_POWER_MA (250) + +#define USBD_ITF_CDC (0) // needs 2 interfaces +#define USBD_ITF_MAX (2) + +#define USBD_CDC_EP_CMD (0x81) +#define USBD_CDC_EP_OUT (0x02) +#define USBD_CDC_EP_IN (0x82) +#define USBD_CDC_CMD_MAX_SIZE (8) + +#define USBD_STR_0 (0x00) +#define USBD_STR_MANUF (0x01) +#define USBD_STR_PRODUCT (0x02) +#define USBD_STR_SERIAL (0x03) +#define USBD_STR_CDC (0x04) + +// Note: descriptors returned from callbacks must exist long enough for transfer to complete + +static const tusb_desc_device_t usbd_desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100, + .iManufacturer = USBD_STR_MANUF, + .iProduct = USBD_STR_PRODUCT, + .iSerialNumber = USBD_STR_SERIAL, + .bNumConfigurations = 1, +}; + +static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { + TUD_CONFIG_DESCRIPTOR(USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), + + TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, + USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, CFG_TUD_CDC_RX_BUFSIZE), +}; + +static const char *const usbd_desc_str[] = { + [USBD_STR_MANUF] = "MicroPython", + [USBD_STR_PRODUCT] = "Board in FS mode", + [USBD_STR_SERIAL] = "000000000000", // TODO + [USBD_STR_CDC] = "Board CDC", +}; + +const uint8_t *tud_descriptor_device_cb(void) { + return (const uint8_t*)&usbd_desc_device; +} + +const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; + return usbd_desc_cfg; +} + +const uint16_t *tud_descriptor_string_cb(uint8_t index) { + #define DESC_STR_MAX (20) + static uint16_t desc_str[DESC_STR_MAX]; + + uint8_t len; + if (index == 0) { + desc_str[1] = 0x0409; // supported language is English + len = 1; + } else { + if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { + return NULL; + } + const char* str = usbd_desc_str[index]; + for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { + desc_str[1 + len] = str[len]; + } + } + + // first byte is len, second byte is string type + desc_str[0] = TUD_DESC_STR_HEADER(len); + + return desc_str; +} + +#if defined(MCU_SAMD21) + +void USB_Handler_wrapper(void) { + USB_Handler(); + tud_task(); +} + +#elif defined(MCU_SAMD51) + +void USB_0_Handler_wrapper(void) { + USB_0_Handler(); + tud_task(); +} + +void USB_1_Handler_wrapper(void) { + USB_1_Handler(); + tud_task(); +} + +void USB_2_Handler_wrapper(void) { + USB_2_Handler(); + tud_task(); +} + +void USB_3_Handler_wrapper(void) { + USB_3_Handler(); + tud_task(); +} + +#endif From 9ca478913040d0fe6fe72582a432c400ec1386ac Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 22 Jun 2019 23:06:42 +1000 Subject: [PATCH 0207/1299] travis: Add samd port to Travis build. --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9fbdb1698eb88..284d311f7e112 100644 --- a/.travis.yml +++ b/.travis.yml @@ -188,6 +188,16 @@ jobs: - make ${MAKEOPTS} -C ports/cc3200 BTARGET=application BTYPE=release - make ${MAKEOPTS} -C ports/cc3200 BTARGET=bootloader BTYPE=release + # samd port + - stage: test + env: NAME="samd port build" + install: + - sudo apt-get install gcc-arm-none-eabi + - sudo apt-get install libnewlib-arm-none-eabi + script: + - git submodule update --init lib/asf4 lib/tinyusb + - make ${MAKEOPTS} -C ports/samd + # teensy port - stage: test env: NAME="teensy port build" From 999733b1fb08fb07a31846115998dbf43a913327 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 1 Jul 2019 22:41:47 +1000 Subject: [PATCH 0208/1299] minimal: Use soft float for CROSS=1 Cortex-M4 target. When compiled with hard float the system should enable FP access when it starts or else FP instructions lead to a fault. But this minimal port does not enable (or use) FP and so, to keep it minimal, switch to use soft floating point. (This became an issue due to the recent commit 34c04d2319cdfae01ed7bf7f9e341d69b86d751a which saves/restores FP registers in the NLR state.) --- ports/minimal/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index 64ad3cc0b2129..b3e27509f1671 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -19,7 +19,7 @@ INC += -I$(BUILD) ifeq ($(CROSS), 1) DFU = $(TOP)/tools/dfu.py PYDFU = $(TOP)/tools/pydfu.py -CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion +CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -fsingle-precision-constant -Wdouble-promotion CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref --gc-sections else From 89a23a05b3feb2f81fb00d272202b274c2a325cd Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 24 Jun 2019 13:18:43 +1000 Subject: [PATCH 0209/1299] esp8266: Provide custom machine_time_pulse_us that feeds soft WDT. So that the timeout for machine.time_pulse_us() can be large. Fixes issue #2775. --- extmod/machine_pulse.c | 2 +- ports/esp8266/modmachine.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c index 5f837479dd61c..7178b22d791ec 100644 --- a/extmod/machine_pulse.c +++ b/extmod/machine_pulse.c @@ -30,7 +30,7 @@ #if MICROPY_PY_MACHINE_PULSE -mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { +MP_WEAK mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { mp_uint_t start = mp_hal_ticks_us(); while (mp_hal_pin_read(pin) != pulse_level) { if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) { diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index ccde1e5ed89a3..e20e8cb75710e 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -355,6 +355,35 @@ STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) { } MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); +// Custom version of this function that feeds system WDT if necessary +mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) { + int nchanges = 2; + uint32_t start = system_get_time(); // in microseconds + for (;;) { + uint32_t dt = system_get_time() - start; + + // Check if pin changed to wanted value + if (mp_hal_pin_read(pin) == pulse_level) { + if (--nchanges == 0) { + return dt; + } + pulse_level = 1 - pulse_level; + start = system_get_time(); + continue; + } + + // Check for timeout + if (dt >= timeout_us) { + return (mp_uint_t)-nchanges; + } + + // Only feed WDT every now and then, to make sure edge timing is accurate + if ((dt & 0xffff) == 0xffff && !ets_loop_dont_feed_sw_wdt) { + system_soft_wdt_feed(); + } + } +} + STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, From 097b0f939754833c3fac40f4a4c8e568bf8ae430 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 24 Jun 2019 13:32:41 +1000 Subject: [PATCH 0210/1299] windows/mpconfigport.h: Define empty MP_WEAK symbol. --- ports/windows/mpconfigport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 81464d72a7f13..86e44183bfeb5 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -214,6 +214,7 @@ extern const struct _mp_obj_module_t mp_module_time; // CL specific overrides from mpconfig #define NORETURN __declspec(noreturn) +#define MP_WEAK #define MP_NOINLINE __declspec(noinline) #define MP_LIKELY(x) (x) #define MP_UNLIKELY(x) (x) From 2920d26af579363ac9f64a9d941d1a4eff880ffe Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Sun, 30 Jun 2019 11:39:24 +0200 Subject: [PATCH 0211/1299] py/persistentcode: Ensure prelude_offset is always initialised. --- py/persistentcode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index c1ca46f7e90e4..f55478ca0b7c9 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -337,7 +337,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { byte *ip2; bytecode_prelude_t prelude = {0}; #if MICROPY_EMIT_MACHINE_CODE - size_t prelude_offset; + size_t prelude_offset = 0; mp_uint_t type_sig = 0; size_t n_qstr_link = 0; #endif From 08075beeb9b45557f8ed6970e4e3e4a00bd26879 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 2 Jul 2019 17:09:59 +1000 Subject: [PATCH 0212/1299] samd: Remove "makefile" file. This file can be added by a user to customise the build process. --- ports/samd/makefile | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 ports/samd/makefile diff --git a/ports/samd/makefile b/ports/samd/makefile deleted file mode 100644 index 336d6f2800003..0000000000000 --- a/ports/samd/makefile +++ /dev/null @@ -1,12 +0,0 @@ -#BOARD = TRINKET -UF2DEV = /dev/sdb -#UF2CONV = /home/damien/others/uf2/utils/uf2conv.py - -include Makefile - -deploy: $(BUILD)/firmware.uf2 - $(ECHO) "Copying $< to the board" - mount $(UF2DEV) - cat /mnt/INFO_UF2.TXT > /dev/null - cp $< /mnt - umount /mnt From 62b00dd5d8cd6207147d37222e1c249ef6381841 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 27 Jun 2019 13:36:15 -0500 Subject: [PATCH 0213/1299] py/asmarm: Use __clear_cache on Linux/GCC when creating new asm code. Comes from https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/caches-and-self-modifying-code This fixes a crash when running MicroPython using qemu-arm. --- py/asmarm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/py/asmarm.c b/py/asmarm.c index f2221f8a92642..2a84f985ba7ee 100644 --- a/py/asmarm.c +++ b/py/asmarm.c @@ -40,7 +40,11 @@ void asm_arm_end_pass(asm_arm_t *as) { if (as->base.pass == MP_ASM_PASS_EMIT) { -#ifdef __arm__ +#if defined(__linux__) && defined(__GNUC__) + char *start = mp_asm_base_get_code(&as->base); + char *end = start + mp_asm_base_get_code_size(&as->base); + __clear_cache(start, end); +#elif defined(__arm__) // flush I- and D-cache asm volatile( "0:" From f3a5b313e55e8853928702eec16c932481f370fc Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 27 Jun 2019 16:43:05 -0500 Subject: [PATCH 0214/1299] py/nlrthumb: Check __thumb2__ instead of __ARM_ARCH_6M__. This fixes compiling for older architectures (e.g. armv5tej). According to [1], the limit of R0-R7 for the STR and LDR instructions is tied to the Thumb instruction set and not any specific processor architectures. [1]: http://www.keil.com/support/man/docs/armasm/armasm_dom1361289906890.htm --- py/nlrthumb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/py/nlrthumb.c b/py/nlrthumb.c index 32fa6b1176436..eef05229d693f 100644 --- a/py/nlrthumb.c +++ b/py/nlrthumb.c @@ -44,7 +44,7 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { "str r6, [r0, #20] \n" // store r6 into nlr_buf "str r7, [r0, #24] \n" // store r7 into nlr_buf -#if defined(__ARM_ARCH_6M__) +#if !defined(__thumb2__) "mov r1, r8 \n" "str r1, [r0, #28] \n" // store r8 into nlr_buf "mov r1, r9 \n" @@ -71,7 +71,7 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { "str lr, [r0, #8] \n" // store lr into nlr_buf #endif -#if defined(__ARM_ARCH_6M__) +#if !defined(__thumb2__) "ldr r1, nlr_push_tail_var \n" "bx r1 \n" // do the rest in C ".align 2 \n" @@ -102,7 +102,7 @@ NORETURN void nlr_jump(void *val) { "ldr r6, [r0, #20] \n" // load r6 from nlr_buf "ldr r7, [r0, #24] \n" // load r7 from nlr_buf -#if defined(__ARM_ARCH_6M__) +#if !defined(__thumb2__) "ldr r1, [r0, #28] \n" // load r8 from nlr_buf "mov r8, r1 \n" "ldr r1, [r0, #32] \n" // load r9 from nlr_buf From 8dcf25e1bd9bfd1c6d8723b6a2d9c27615b109c2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 00:46:20 +1000 Subject: [PATCH 0215/1299] stm32/mpu: Add helper functions for configuring MPU. --- ports/stm32/main.c | 3 ++ ports/stm32/mpu.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 ports/stm32/mpu.h diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 2dcc09ae7a445..1a1c505dc4805 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -43,6 +43,7 @@ #include "drivers/cyw43/cyw43.h" #endif +#include "mpu.h" #include "systick.h" #include "pendsv.h" #include "powerctrl.h" @@ -409,6 +410,8 @@ void stm32_main(uint32_t reset_mode) { #endif + mpu_init(); + #if __CORTEX_M >= 0x03 // Set the priority grouping NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); diff --git a/ports/stm32/mpu.h b/ports/stm32/mpu.h new file mode 100644 index 0000000000000..d90a768e7a80b --- /dev/null +++ b/ports/stm32/mpu.h @@ -0,0 +1,74 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_MPU_H +#define MICROPY_INCLUDED_STM32_MPU_H + +#if defined(STM32F7) || defined(STM32H7) + +#define MPU_CONFIG_DISABLE(srd, size) ( \ + MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos \ + | MPU_REGION_NO_ACCESS << MPU_RASR_AP_Pos \ + | MPU_TEX_LEVEL0 << MPU_RASR_TEX_Pos \ + | MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos \ + | MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos \ + | MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos \ + | (srd) << MPU_RASR_SRD_Pos \ + | (size) << MPU_RASR_SIZE_Pos \ + | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ + ) + +static inline void mpu_init(void) { + MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; + __DSB(); + __ISB(); +} + +static inline void mpu_config_start(void) { + __disable_irq(); +} + +static inline void mpu_config_region(uint32_t region, uint32_t base_addr, uint32_t attr_size) { + MPU->RNR = region; + MPU->RBAR = base_addr; + MPU->RASR = attr_size; +} + +static inline void mpu_config_end(void) { + __ISB(); + __DSB(); + __DMB(); + __enable_irq(); +} + +#else + +static inline void mpu_init(void) { +} + +#endif + +#endif // MICROPY_INCLUDED_STM32_MPU_H From f7eb2c72f76be6033a32247c145128153e3449ac Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 00:47:32 +1000 Subject: [PATCH 0216/1299] stm32/eth: Use MPU helper functions to configure MPU for ETH use. --- ports/stm32/eth.c | 34 ++++------------------------------ ports/stm32/mpu.h | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/ports/stm32/eth.c b/ports/stm32/eth.c index 6a1ef99afa3ba..9633d32b280a2 100644 --- a/ports/stm32/eth.c +++ b/ports/stm32/eth.c @@ -30,6 +30,7 @@ #include "lib/netutils/netutils.h" #include "pin_static_af.h" #include "modnetwork.h" +#include "mpu.h" #include "eth.h" #if defined(MICROPY_HW_ETH_MDC) @@ -141,35 +142,6 @@ STATIC uint32_t eth_phy_read(uint32_t reg) { return ETH->MACMIIDR; } -STATIC void mpu_config(uint32_t region, uint32_t base_addr, uint32_t size) { - __DMB(); - - // Disable MPU - SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; - MPU->CTRL = 0; - - // Config MPU region - MPU->RNR = region; - MPU->RBAR = base_addr; - MPU->RASR = - MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos - | MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos - | MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos - | MPU_ACCESS_SHAREABLE << MPU_RASR_S_Pos - | MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos - | MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos - | 0x00 << MPU_RASR_SRD_Pos - | size << MPU_RASR_SIZE_Pos - | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos; - - // Enable MPU - MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - - __DSB(); - __ISB(); -} - void eth_init(eth_t *self, int mac_idx) { mp_hal_get_mac(mac_idx, &self->netif.hwaddr[0]); self->netif.hwaddr_len = 6; @@ -181,7 +153,9 @@ void eth_set_trace(eth_t *self, uint32_t value) { STATIC int eth_mac_init(eth_t *self) { // Configure MPU - mpu_config(MPU_REGION_NUMBER0, (uint32_t)ð_dma, MPU_REGION_SIZE_16KB); + mpu_config_start(); + mpu_config_region(MPU_REGION_ETH, (uint32_t)ð_dma, MPU_CONFIG_ETH(MPU_REGION_SIZE_16KB)); + mpu_config_end(); // Configure GPIO mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDC); diff --git a/ports/stm32/mpu.h b/ports/stm32/mpu.h index d90a768e7a80b..c0cd2108c1749 100644 --- a/ports/stm32/mpu.h +++ b/ports/stm32/mpu.h @@ -28,6 +28,8 @@ #if defined(STM32F7) || defined(STM32H7) +#define MPU_REGION_ETH (MPU_REGION_NUMBER0) + #define MPU_CONFIG_DISABLE(srd, size) ( \ MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos \ | MPU_REGION_NO_ACCESS << MPU_RASR_AP_Pos \ @@ -40,6 +42,18 @@ | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ ) +#define MPU_CONFIG_ETH(size) ( \ + MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos \ + | MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos \ + | MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos \ + | MPU_ACCESS_SHAREABLE << MPU_RASR_S_Pos \ + | MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos \ + | MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos \ + | 0x00 << MPU_RASR_SRD_Pos \ + | (size) << MPU_RASR_SIZE_Pos \ + | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ + ) + static inline void mpu_init(void) { MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; From eca4115f666f8b5e1e0155ce930353b698dcd7ef Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 00:48:19 +1000 Subject: [PATCH 0217/1299] stm32/sdram: Use MPU helper functions to configure MPU for SDRAM use. --- ports/stm32/mpu.h | 14 ++++++++++++++ ports/stm32/sdram.c | 41 +++++------------------------------------ 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/ports/stm32/mpu.h b/ports/stm32/mpu.h index c0cd2108c1749..c5881d8fded4b 100644 --- a/ports/stm32/mpu.h +++ b/ports/stm32/mpu.h @@ -29,6 +29,8 @@ #if defined(STM32F7) || defined(STM32H7) #define MPU_REGION_ETH (MPU_REGION_NUMBER0) +#define MPU_REGION_SDRAM1 (MPU_REGION_NUMBER4) +#define MPU_REGION_SDRAM2 (MPU_REGION_NUMBER5) #define MPU_CONFIG_DISABLE(srd, size) ( \ MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos \ @@ -54,6 +56,18 @@ | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ ) +#define MPU_CONFIG_SDRAM(size) ( \ + MPU_INSTRUCTION_ACCESS_ENABLE << MPU_RASR_XN_Pos \ + | MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos \ + | MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos \ + | MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos \ + | MPU_ACCESS_CACHEABLE << MPU_RASR_C_Pos \ + | MPU_ACCESS_BUFFERABLE << MPU_RASR_B_Pos \ + | 0x00 << MPU_RASR_SRD_Pos \ + | (size) << MPU_RASR_SIZE_Pos \ + | MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos \ + ) + static inline void mpu_init(void) { MPU->CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk; SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index b3c5bbeeed9b6..5d54dc2cb33cf 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -13,6 +13,7 @@ #include "py/mphal.h" #include "pin.h" #include "pin_static_af.h" +#include "mpu.h" #include "systick.h" #include "sdram.h" @@ -244,45 +245,13 @@ static void sdram_init_seq(SDRAM_HandleTypeDef #if defined(STM32F7) /* Enable MPU for the SDRAM Memory Region to allow non-aligned accesses (hard-fault otherwise) - */ - - MPU_Region_InitTypeDef MPU_InitStruct; - - /* Disable the MPU */ - HAL_MPU_Disable(); - - /* Configure the MPU attributes for External SDRAM Initially disable all access for the entire SDRAM memory space, then enable access/caching for the size used */ - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER4; - MPU_InitStruct.BaseAddress = SDRAM_START_ADDRESS; - MPU_InitStruct.Size = MPU_REGION_SIZE_512MB; - MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.SubRegionDisable = 0x00; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER5; - MPU_InitStruct.BaseAddress = SDRAM_START_ADDRESS; - MPU_InitStruct.Size = SDRAM_MPU_REGION_SIZE; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; - MPU_InitStruct.SubRegionDisable = 0x00; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); - - /* Enable the MPU */ - HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); + mpu_config_start(); + mpu_config_region(MPU_REGION_SDRAM1, SDRAM_START_ADDRESS, MPU_CONFIG_DISABLE(0x00, MPU_REGION_SIZE_512MB)); + mpu_config_region(MPU_REGION_SDRAM2, SDRAM_START_ADDRESS, MPU_CONFIG_SDRAM(SDRAM_MPU_REGION_SIZE)); + mpu_config_end(); #endif } From 8da39fd182aee0f357c34d8e17f54601c078f6e0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 00:50:32 +1000 Subject: [PATCH 0218/1299] stm32/qspi: Use MPU to allow access to valid memory-mapped QSPI region. The Cortex-M7 CPU will do speculative loads from any memory location that is not explicitly forbidden. This includes the QSPI memory-mapped region starting at 0x90000000 and with size 256MiB. Speculative loads to this QSPI region may 1) interfere with the QSPI peripheral registers (eg the address register) if the QSPI is not in memory-mapped mode; 2) attempt to access data outside the configured size of the QSPI flash when it is in memory-mapped mode. Both of these scenarios will lead to issues with the QSPI peripheral (eg Cortex bus lock up in scenario 2). To prevent such speculative loads from interfering with the peripheral the MPU is configured in this commit to restrict access to the QSPI mapped region: when not memory mapped the entire region is forbidden; when memory mapped only accesses to the valid flash size are permitted. --- ports/stm32/mpu.h | 3 +++ ports/stm32/qspi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/ports/stm32/mpu.h b/ports/stm32/mpu.h index c5881d8fded4b..2541d86bfb41b 100644 --- a/ports/stm32/mpu.h +++ b/ports/stm32/mpu.h @@ -29,6 +29,9 @@ #if defined(STM32F7) || defined(STM32H7) #define MPU_REGION_ETH (MPU_REGION_NUMBER0) +#define MPU_REGION_QSPI1 (MPU_REGION_NUMBER1) +#define MPU_REGION_QSPI2 (MPU_REGION_NUMBER2) +#define MPU_REGION_QSPI3 (MPU_REGION_NUMBER3) #define MPU_REGION_SDRAM1 (MPU_REGION_NUMBER4) #define MPU_REGION_SDRAM2 (MPU_REGION_NUMBER5) diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 8c8b9c4940832..8ed3a17dd5c4f 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -28,11 +28,14 @@ #include "py/mperrno.h" #include "py/mphal.h" +#include "mpu.h" #include "qspi.h" #include "pin_static_af.h" #if defined(MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2) +#define QSPI_MAP_ADDR (0x90000000) + #ifndef MICROPY_HW_QSPI_PRESCALER #define MICROPY_HW_QSPI_PRESCALER 3 // F_CLK = F_AHB/3 (72MHz when CPU is 216MHz) #endif @@ -49,7 +52,31 @@ #define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles #endif +static inline void qspi_mpu_disable_all(void) { + // Configure MPU to disable access to entire QSPI region, to prevent CPU + // speculative execution from accessing this region and modifying QSPI registers. + mpu_config_start(); + mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x00, MPU_REGION_SIZE_256MB)); + mpu_config_end(); +} + +static inline void qspi_mpu_enable_mapped(void) { + // Configure MPU to allow access to only the valid part of external SPI flash. + // The memory accesses to the mapped QSPI are faster if the MPU is not used + // for the memory-mapped region, so 3 MPU regions are used to disable access + // to everything except the valid address space, using holes in the bottom + // of the regions and nesting them. + // At the moment this is hard-coded to 2MiB of QSPI address space. + mpu_config_start(); + mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB)); + mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0f, MPU_REGION_SIZE_32MB)); + mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_16MB)); + mpu_config_end(); +} + void qspi_init(void) { + qspi_mpu_disable_all(); + // Configure pins mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_CS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_BK1_NCS); mp_hal_pin_config_alt_static_speed(MICROPY_HW_QSPIFLASH_SCK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_QUADSPI_CLK); @@ -100,6 +127,8 @@ void qspi_memory_map(void) { | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | 0xeb << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode ; + + qspi_mpu_enable_mapped(); } STATIC int qspi_ioctl(void *self_in, uint32_t cmd) { From 2034c0a2e364404216c8cadeb661fbc72647d16a Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 00:59:56 +1000 Subject: [PATCH 0219/1299] stm32/qspi: Force a reset of the QSPI peripheral when initialising it. To ensure it is in a known state on start up. --- ports/stm32/qspi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 8ed3a17dd5c4f..282759967e7c9 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -88,6 +88,8 @@ void qspi_init(void) { // Bring up the QSPI peripheral __HAL_RCC_QSPI_CLK_ENABLE(); + __HAL_RCC_QSPI_FORCE_RESET(); + __HAL_RCC_QSPI_RELEASE_RESET(); QUADSPI->CR = (MICROPY_HW_QSPI_PRESCALER - 1) << QUADSPI_CR_PRESCALER_Pos From caabdd99c0f8402f5a141123f02cdf4be0a10ecf Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 01:00:40 +1000 Subject: [PATCH 0220/1299] stm32/qspi: Handle bus acquisition. When going out of memory-mapped mode to do a control transfer to the QSPI flash, the MPU settings must be changed to forbid access to the memory mapped region. And any ongoing transfer (eg memory mapped continuous read) must be aborted. --- ports/stm32/qspi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 282759967e7c9..ec744bfb27fc4 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -139,6 +139,16 @@ STATIC int qspi_ioctl(void *self_in, uint32_t cmd) { case MP_QSPI_IOCTL_INIT: qspi_init(); break; + case MP_QSPI_IOCTL_BUS_ACQUIRE: + // Disable memory-mapped region during bus access + qspi_mpu_disable_all(); + // Abort any ongoing transfer if peripheral is busy + if (QUADSPI->SR & QUADSPI_SR_BUSY) { + QUADSPI->CR |= QUADSPI_CR_ABORT; + while (QUADSPI->CR & QUADSPI_CR_ABORT) { + } + } + break; case MP_QSPI_IOCTL_BUS_RELEASE: // Switch to memory-map mode when bus is idle qspi_memory_map(); From 8cde5faedd63ea1b21b7adef87e50e6a036c7e5a Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 01:03:25 +1000 Subject: [PATCH 0221/1299] drivers/memory/spiflash: Add support to put SPI flash in sleep mode. --- drivers/memory/spiflash.c | 17 +++++++++++++++++ drivers/memory/spiflash.h | 1 + 2 files changed, 18 insertions(+) diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c index 22775d5416fc2..0eacc710e3475 100644 --- a/drivers/memory/spiflash.c +++ b/drivers/memory/spiflash.c @@ -146,6 +146,10 @@ STATIC int mp_spiflash_wait_wip0(mp_spiflash_t *self) { return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT); } +static inline void mp_spiflash_deepsleep_internal(mp_spiflash_t *self, int value) { + mp_spiflash_write_cmd(self, value ? 0xb9 : 0xab); // sleep/wake +} + void mp_spiflash_init(mp_spiflash_t *self) { self->flags = 0; @@ -159,6 +163,9 @@ void mp_spiflash_init(mp_spiflash_t *self) { mp_spiflash_acquire_bus(self); + // Ensure SPI flash is out of sleep mode + mp_spiflash_deepsleep_internal(self, 0); + #if defined(CHECK_DEVID) // Validate device id uint32_t devid = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3); @@ -182,6 +189,16 @@ void mp_spiflash_init(mp_spiflash_t *self) { mp_spiflash_release_bus(self); } +void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) { + if (value) { + mp_spiflash_acquire_bus(self); + } + mp_spiflash_deepsleep_internal(self, value); + if (!value) { + mp_spiflash_release_bus(self); + } +} + STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) { // enable writes mp_spiflash_write_cmd(self, CMD_WREN); diff --git a/drivers/memory/spiflash.h b/drivers/memory/spiflash.h index a5b8a1dcaebe9..96dfdeeab66bf 100644 --- a/drivers/memory/spiflash.h +++ b/drivers/memory/spiflash.h @@ -68,6 +68,7 @@ typedef struct _mp_spiflash_t { } mp_spiflash_t; void mp_spiflash_init(mp_spiflash_t *self); +void mp_spiflash_deepsleep(mp_spiflash_t *self, int value); // These functions go direct to the SPI flash device int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr); From ea033bf25a08c26b8b43fc316c797ae6526a894f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 01:04:25 +1000 Subject: [PATCH 0222/1299] stm32/powerctrl: Add hooks for a board to perform actions on sleep/wake. --- ports/stm32/powerctrl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 2ad24260051e7..e3ad20039c2d8 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -324,6 +324,10 @@ void powerctrl_enter_stop_mode(void) { // executed until after the clocks are reconfigured uint32_t irq_state = disable_irq(); + #if defined(MICROPY_BOARD_ENTER_STOP) + MICROPY_BOARD_ENTER_STOP + #endif + #if defined(STM32L4) // Configure the MSI as the clock source after waking up __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); @@ -399,6 +403,10 @@ void powerctrl_enter_stop_mode(void) { #endif + #if defined(MICROPY_BOARD_LEAVE_STOP) + MICROPY_BOARD_LEAVE_STOP + #endif + // Enable IRQs now that all clocks are reconfigured enable_irq(irq_state); } @@ -406,6 +414,10 @@ void powerctrl_enter_stop_mode(void) { void powerctrl_enter_standby_mode(void) { rtc_init_finalise(); + #if defined(MICROPY_BOARD_ENTER_STANDBY) + MICROPY_BOARD_ENTER_STANDBY + #endif + // We need to clear the PWR wake-up-flag before entering standby, since // the flag may have been set by a previous wake-up event. Furthermore, // we need to disable the wake-up sources while clearing this flag, so From d821a27b584740c21d451a882f7ca58d01486021 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 01:05:39 +1000 Subject: [PATCH 0223/1299] stm32/boards/PYBD_SFx: Put SPI flash to sleep during sleep modes. --- ports/stm32/boards/PYBD_SF2/board_init.c | 5 +++++ ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/board_init.c b/ports/stm32/boards/PYBD_SF2/board_init.c index 3dc2c85e22a21..8438b82317631 100644 --- a/ports/stm32/boards/PYBD_SF2/board_init.c +++ b/ports/stm32/boards/PYBD_SF2/board_init.c @@ -36,3 +36,8 @@ void board_early_init(void) { // Explicitly init SPI2 because it's not enabled as a block device spi_bdev_ioctl(&spi_bdev2, BDEV_IOCTL_INIT, (uint32_t)&spiflash2_config); } + +void board_sleep(int value) { + mp_spiflash_deepsleep(&spi_bdev.spiflash, value); + mp_spiflash_deepsleep(&spi_bdev2.spiflash, value); +} diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index 56650ba1580c1..a46b5ca5bc7a9 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -41,7 +41,11 @@ #define MICROPY_HW_ENABLE_MMCARD (1) #define MICROPY_BOARD_EARLY_INIT board_early_init +#define MICROPY_BOARD_ENTER_STOP board_sleep(1); +#define MICROPY_BOARD_LEAVE_STOP board_sleep(0); +#define MICROPY_BOARD_ENTER_STANDBY board_sleep(1); void board_early_init(void); +void board_sleep(int value); // HSE is 25MHz, run SYS at 120MHz #define MICROPY_HW_CLK_PLLM (20) From 6d2e654b1411d0816c8f7eaa159b9c57a2617859 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 11:21:45 +1000 Subject: [PATCH 0224/1299] stm32/mpconfigport.h: Enable useful networking modules if lwIP enabled. --- ports/stm32/mpconfigport.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index d802300637f72..5095dde52b8d8 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -139,6 +139,9 @@ #define MICROPY_PY_URE_SUB (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UHASHLIB (1) +#define MICROPY_PY_UHASHLIB_MD5 (MICROPY_PY_USSL) +#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL) +#define MICROPY_PY_UCRYPTOLIB (MICROPY_PY_USSL) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) @@ -160,6 +163,8 @@ #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hard_spi_make_new #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (HAL_RCC_GetSysClockFreq() / 48) +#define MICROPY_PY_UWEBSOCKET (MICROPY_PY_LWIP) +#define MICROPY_PY_WEBREPL (MICROPY_PY_LWIP) #define MICROPY_PY_FRAMEBUF (1) #ifndef MICROPY_PY_USOCKET #define MICROPY_PY_USOCKET (1) From 46b3cc4572036c9e2185b4aa8fb77dff29967680 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 11:51:13 +1000 Subject: [PATCH 0225/1299] stm32/usb: Add support to auto-detect USB interface, either FS or HS. If both FS and HS USB peripherals are enabled for a board then the active one used for the REPL will now be auto-detected, by checking to see if both the DP and DM lines are actively pulled low. By default the code falls back to use MICROPY_HW_USB_MAIN_DEV if nothing can be detected. --- ports/stm32/main.c | 2 +- ports/stm32/usb.c | 31 ++++++++++++++++++++++++++++--- ports/stm32/usb.h | 3 ++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 1a1c505dc4805..e470522fbd515 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -652,7 +652,7 @@ void stm32_main(uint32_t reset_mode) { #if MICROPY_HW_ENABLE_USB // init USB device to default setting if it was not already configured if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) { - pyb_usb_dev_init(USBD_VID, USBD_PID_CDC_MSC, USBD_MODE_CDC_MSC, 0, NULL, NULL); + pyb_usb_dev_init(pyb_usb_dev_detect(), USBD_VID, USBD_PID_CDC_MSC, USBD_MODE_CDC_MSC, 0, NULL, NULL); } #endif diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 69ba26c43864b..12e138818524d 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -120,14 +120,39 @@ void pyb_usb_init0(void) { pyb_usb_vcp_init0(); } -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info) { +int pyb_usb_dev_detect(void) { + if (usb_device.enabled) { + return usb_device.hUSBDDevice.id; + } + + #if MICROPY_HW_USB_FS && MICROPY_HW_USB_HS + // Try to auto-detect which USB is connected by reading DP/DM pins + for (int i = 0; i < 2; ++i) { + mp_hal_pin_obj_t dp = i == 0 ? pyb_pin_USB_DP : pyb_pin_USB_HS_DP; + mp_hal_pin_obj_t dm = i == 0 ? pyb_pin_USB_DM : pyb_pin_USB_HS_DM; + mp_hal_pin_config(dp, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); + mp_hal_pin_config(dm, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); + int state = mp_hal_pin_read(dp) == 0 && mp_hal_pin_read(dm) == 0; + mp_hal_pin_config(dp, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); + mp_hal_pin_config(dm, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0); + if (state) { + // DP and DM pins are actively held low so assume USB is connected + return i == 0 ? USB_PHY_FS_ID : USB_PHY_HS_ID; + } + } + #endif + + return MICROPY_HW_USB_MAIN_DEV; +} + +bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info) { usb_device_t *usb_dev = &usb_device; if (!usb_dev->enabled) { // only init USB once in the device's power-lifetime // set up the USBD state USBD_HandleTypeDef *usbd = &usb_dev->hUSBDDevice; - usbd->id = MICROPY_HW_USB_MAIN_DEV; + usbd->id = dev_id; usbd->dev_state = USBD_STATE_DEFAULT; usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors; usbd->pClass = &USBD_CDC_MSC_HID; @@ -403,7 +428,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * #endif // init the USB device - if (!pyb_usb_dev_init(vid, pid, mode, msc_n, msc_unit, &hid_info)) { + if (!pyb_usb_dev_init(pyb_usb_dev_detect(), vid, pid, mode, msc_n, msc_unit, &hid_info)) { goto bad_mode; } diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index b1c8b476a7d8e..cb017902ecb50 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -66,7 +66,8 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated void pyb_usb_init0(void); -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info); +int pyb_usb_dev_detect(void); +bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size_t msc_n, const void *msc_unit, USBD_HID_ModeInfoTypeDef *hid_info); void pyb_usb_dev_deinit(void); bool usb_vcp_is_enabled(void); int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0 From f114ce0a4b43474a73e9e5ddddbcf9a36553f954 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 11:58:56 +1000 Subject: [PATCH 0226/1299] stm32/usb: Add "port" keyword argument to pyb.usb_mode, to select FS/HS. If the board supports it, the USB port can now be explicitly specified, eg: pyb.usb_mode('VCP', port=0). port=0 is USB FS and port=1 is USB HS. --- ports/stm32/usb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 12e138818524d..51e6e7a39249a 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -255,9 +255,10 @@ usbd_cdc_itf_t *usb_vcp_get(int idx) { */ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_vid, ARG_pid, ARG_msc, ARG_hid, ARG_high_speed }; + enum { ARG_mode, ARG_port, ARG_vid, ARG_pid, ARG_msc, ARG_hid, ARG_high_speed }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_vid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = USBD_VID} }, { MP_QSTR_pid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_msc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_empty_tuple_obj)} }, @@ -427,8 +428,14 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * } #endif + // Work out which port/peripheral to use, either user supplied or auto detect + int dev_id = args[ARG_port].u_int; + if (dev_id == -1) { + dev_id = pyb_usb_dev_detect(); + } + // init the USB device - if (!pyb_usb_dev_init(pyb_usb_dev_detect(), vid, pid, mode, msc_n, msc_unit, &hid_info)) { + if (!pyb_usb_dev_init(dev_id, vid, pid, mode, msc_n, msc_unit, &hid_info)) { goto bad_mode; } From 14bec7964fa49d905521caf697d94401eb789cfa Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 12:02:46 +1000 Subject: [PATCH 0227/1299] stm32/spi: Factor out code to calculate SPI source frequency. --- ports/stm32/spi.c | 86 ++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 53 deletions(-) diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index 545cb3365e6cc..e6336fb5d06b2 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -186,6 +186,37 @@ int spi_find_index(mp_obj_t id) { } } +STATIC uint32_t spi_get_source_freq(SPI_HandleTypeDef *spi) { + #if defined(STM32F0) + return HAL_RCC_GetPCLK1Freq(); + #elif defined(STM32H7) + if (spi->Instance == SPI1 || spi->Instance == SPI2 || spi->Instance == SPI3) { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123); + } else if (spi->Instance == SPI4 || spi->Instance == SPI5) { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45); + } else { + return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); + } + #else + #if defined(SPI2) + if (spi->Instance == SPI2) { + // SPI2 is on APB1 + return HAL_RCC_GetPCLK1Freq(); + } else + #endif + #if defined(SPI3) + if (spi->Instance == SPI3) { + // SPI3 is on APB1 + return HAL_RCC_GetPCLK1Freq(); + } else + #endif + { + // SPI1, SPI4, SPI5 and SPI6 are on APB2 + return HAL_RCC_GetPCLK2Freq(); + } + #endif +} + // sets the parameters in the SPI_InitTypeDef struct // if an argument is -1 then the corresponding parameter is not changed void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate, @@ -196,32 +227,7 @@ void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate, if (prescale != 0xffffffff || baudrate != -1) { if (prescale == 0xffffffff) { // prescaler not given, so select one that yields at most the requested baudrate - mp_uint_t spi_clock; - #if defined(STM32F0) - spi_clock = HAL_RCC_GetPCLK1Freq(); - #elif defined(STM32H7) - if (spi->Instance == SPI1 || spi->Instance == SPI2 || spi->Instance == SPI3) { - spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123); - } else if (spi->Instance == SPI4 || spi->Instance == SPI5) { - spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45); - } else { - spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); - } - #else - if (spi->Instance == SPI3) { - // SPI3 is on APB1 - spi_clock = HAL_RCC_GetPCLK1Freq(); - #if defined(SPI2) - } else if (spi->Instance == SPI2) { - // SPI2 is on APB1 - spi_clock = HAL_RCC_GetPCLK1Freq(); - #endif - } else { - // SPI1, SPI4, SPI5 and SPI6 are on APB2 - spi_clock = HAL_RCC_GetPCLK2Freq(); - } - #endif - prescale = (spi_clock + baudrate - 1) / baudrate; + prescale = (spi_get_source_freq(spi) + baudrate - 1) / baudrate; } if (prescale <= 2) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; } else if (prescale <= 4) { init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; } @@ -578,34 +584,8 @@ void spi_print(const mp_print_t *print, const spi_t *spi_obj, bool legacy) { if (spi->State != HAL_SPI_STATE_RESET) { if (spi->Init.Mode == SPI_MODE_MASTER) { // compute baudrate - uint spi_clock; - #if defined(STM32F0) - spi_clock = HAL_RCC_GetPCLK1Freq(); - #elif defined(STM32H7) - if (spi->Instance == SPI1 || spi->Instance == SPI2 || spi->Instance == SPI3) { - spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123); - } else if (spi->Instance == SPI4 || spi->Instance == SPI5) { - spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45); - } else { - spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6); - } - #else - #if defined(SPI2) - if (spi->Instance == SPI2) { - // SPI2 is on APB1 - spi_clock = HAL_RCC_GetPCLK1Freq(); - } else - #endif - if (spi->Instance == SPI3) { - // SPI2 and SPI3 are on APB1 - spi_clock = HAL_RCC_GetPCLK1Freq(); - } else { - // SPI1, SPI4, SPI5 and SPI6 are on APB2 - spi_clock = HAL_RCC_GetPCLK2Freq(); - } - #endif uint log_prescaler = (spi->Init.BaudRatePrescaler >> 3) + 1; - uint baudrate = spi_clock >> log_prescaler; + uint baudrate = spi_get_source_freq(spi) >> log_prescaler; if (legacy) { mp_printf(print, ", SPI.MASTER"); } From 79b66885583925cc0854f32f487627d4d188ed64 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 12:02:58 +1000 Subject: [PATCH 0228/1299] stm32/extint: Simplify bitband support config for different MCUs. --- ports/stm32/extint.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 4a67d1824fb7f..0b1ba8eb09ddb 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -84,11 +84,12 @@ // TODO Add python method to change callback object. +#if defined(STM32F4) || defined(STM32L4) +// These MCUs have bitband support so define macros to atomically set/clear bits in IMR/EMR and SWIER #define EXTI_OFFSET (EXTI_BASE - PERIPH_BASE) - -// Macro used to set/clear the bit corresponding to the line in the IMR/EMR -// register in an atomic fashion by using bitband addressing. #define EXTI_MODE_BB(mode, line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + (mode)) * 32) + ((line) * 4))) +#define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4))) +#endif #if defined(STM32L4) // The L4 MCU supports 40 Events/IRQs lines of the type configurable and direct. @@ -116,8 +117,6 @@ #define EXTI_FTSR EXTI->FTSR #endif -#define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4))) - typedef struct { mp_obj_base_t base; mp_int_t line; @@ -349,8 +348,8 @@ void extint_enable(uint line) { if (line >= EXTI_NUM_VECTORS) { return; } - #if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) - // The Cortex-M7 doesn't have bitband support. + #if !defined(EXTI_MODE_BB) + // This MCU doesn't have bitband support. mp_uint_t irq_state = disable_irq(); if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { #if defined(STM32H7) @@ -379,8 +378,8 @@ void extint_disable(uint line) { return; } - #if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) - // The Cortex-M7 doesn't have bitband support. + #if !defined(EXTI_MODE_BB) + // This MCU doesn't have bitband support. mp_uint_t irq_state = disable_irq(); #if defined(STM32H7) EXTI_D1->IMR1 &= ~(1 << line); @@ -417,8 +416,8 @@ void extint_trigger_mode(uint line, uint32_t mode) { if (line >= EXTI_NUM_VECTORS) { return; } - #if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) - // The Cortex-M7 doesn't have bitband support. + #if !defined(EXTI_MODE_BB) + // This MCU doesn't have bitband support. mp_uint_t irq_state = disable_irq(); // Enable or disable the rising detector if ((mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING) { From fad3d08d2df4b7e62627969510c1507615c5ad3c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 12:47:13 +1000 Subject: [PATCH 0229/1299] extmod/moduwebsocket: Make close_resp static array const to not use RAM. The esp8266 lwip_open library is compiled with -mforce-l32 so this array does not need to be in RAM. --- extmod/moduwebsocket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/moduwebsocket.c b/extmod/moduwebsocket.c index eb5e20c6e3073..d90ee49a74fb8 100644 --- a/extmod/moduwebsocket.c +++ b/extmod/moduwebsocket.c @@ -194,7 +194,7 @@ STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int if (last_state == CONTROL) { byte frame_type = self->last_flags & FRAME_OPCODE_MASK; if (frame_type == FRAME_CLOSE) { - static char close_resp[2] = {0x88, 0}; + static const char close_resp[2] = {0x88, 0}; int err; websocket_write(self_in, close_resp, sizeof(close_resp), &err); return 0; From fa2c7ece8f0c48cab77098f8f4ffe940c459dfee Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 12:50:13 +1000 Subject: [PATCH 0230/1299] extmod/modwebrepl: Make prompt/ver static arrays const to not use RAM. The esp8266 lwip_open library is compiled with -mforce-l32 so these arrays do not need to be in RAM. --- extmod/modwebrepl.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index c9ef77434089c..3c0cfe72f7aab 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -67,10 +67,9 @@ typedef struct _mp_obj_webrepl_t { mp_obj_t cur_file; } mp_obj_webrepl_t; -// These get passed to functions which aren't force-l32, so can't be const -STATIC char passwd_prompt[] = "Password: "; -STATIC char connected_prompt[] = "\r\nWebREPL connected\r\n>>> "; -STATIC char denied_prompt[] = "\r\nAccess denied\r\n"; +STATIC const char passwd_prompt[] = "Password: "; +STATIC const char connected_prompt[] = "\r\nWebREPL connected\r\n>>> "; +STATIC const char denied_prompt[] = "\r\nAccess denied\r\n"; STATIC char webrepl_passwd[10]; @@ -138,7 +137,7 @@ STATIC void handle_op(mp_obj_webrepl_t *self) { switch (self->hdr.type) { case GET_VER: { - static char ver[] = {MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO}; + static const char ver[] = {MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO}; write_webrepl(self->sock, ver, sizeof(ver)); self->hdr_to_recv = sizeof(struct webrepl_file); return; From ef00048fed079c922a4e2bc9ce854cc3824e2bfc Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 12:55:57 +1000 Subject: [PATCH 0231/1299] extmod/modwebrepl: Add config option to put filebuf[512] on stack/bss. Since the esp8266 has a small stack this buffer is kept in the BSS. --- extmod/modwebrepl.c | 6 +++++- ports/esp8266/mpconfigport.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 3c0cfe72f7aab..c92d1dc1b0631 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -245,7 +245,11 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int } if (self->data_to_recv != 0) { - static byte filebuf[512]; + // Ports that don't have much available stack can make this filebuf static + #if MICROPY_PY_WEBREPL_STATIC_FILEBUF + static + #endif + byte filebuf[512]; filebuf[0] = *(byte*)buf; mp_uint_t buf_sz = 1; if (--self->data_to_recv != 0) { diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 03be59b06321b..3bf8220282945 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -90,6 +90,7 @@ #define MICROPY_PY_UWEBSOCKET (1) #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_WEBREPL_DELAY (20) +#define MICROPY_PY_WEBREPL_STATIC_FILEBUF (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_OS_DUPTERM (2) From 1d6cb6357a2cde40822712211fb51c4a4bbe41cf Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 15:50:13 +1000 Subject: [PATCH 0232/1299] extmod/modlwip: For TCP send keep trying tcp_write if it returns ERR_MEM If tcp_write returns ERR_MEM then it's not a fatal error but instead means the caller should retry the write later on (and this is what lwIP's netconn API does). This fixes problems where a TCP send would raise OSError(ENOMEM) in situations where the TCP/IP stack is under heavy load. See eg issues #1897 and #1971. --- extmod/modlwip.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 4127d21addea5..aed69f9200061 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -668,7 +668,25 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui u16_t write_len = MIN(available, len); - err_t err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY); + // If tcp_write returns ERR_MEM then there's currently not enough memory to + // queue the write, so wait and keep trying until it succeeds (with 10s limit). + // Note: if the socket is non-blocking then this code will actually block until + // there's enough memory to do the write, but by this stage we have already + // committed to being able to write the data. + err_t err; + for (int i = 0; i < 200; ++i) { + err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY); + if (err != ERR_MEM) { + break; + } + err = tcp_output(socket->pcb.tcp); + if (err != ERR_OK) { + break; + } + MICROPY_PY_LWIP_EXIT + mp_hal_delay_ms(50); + MICROPY_PY_LWIP_REENTER + } // If the output buffer is getting full then send the data to the lower layers if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) { From c60caf19951c8326be9c3b6f3b016a4d21f69276 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 16:22:48 +1000 Subject: [PATCH 0233/1299] extmod/modlwip: Use mp_sched_schedule to schedule socket callbacks. The helper function exec_user_callback executes within the context of an lwIP C callback, and the user (Python) callback to be scheduled may want to perform further TCP/IP actions, so the latter should be scheduled to run outside the lwIP context (otherwise it's effectively a "hard IRQ" and such callbacks have lots of restrictions). --- extmod/modlwip.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index aed69f9200061..be932b6a9d276 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -356,7 +356,8 @@ STATIC void lwip_socket_free_incoming(lwip_socket_obj_t *socket) { static inline void exec_user_callback(lwip_socket_obj_t *socket) { if (socket->callback != MP_OBJ_NULL) { - mp_call_function_1_protected(socket->callback, MP_OBJ_FROM_PTR(socket)); + // Schedule the user callback to execute outside the lwIP context + mp_sched_schedule(socket->callback, MP_OBJ_FROM_PTR(socket)); } } @@ -446,18 +447,6 @@ STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pb return ERR_BUF; } -// "Poll" (idle) callback to be called ASAP after accept callback -// to execute Python callback function, as it can't be executed -// from accept callback itself. -STATIC err_t _lwip_tcp_accept_finished(void *arg, struct tcp_pcb *pcb) -{ - // The ->connected entry of the pcb holds the listening socket of the accept - lwip_socket_obj_t *socket = (lwip_socket_obj_t*)pcb->connected; - tcp_poll(pcb, NULL, 0); - exec_user_callback(socket); - return ERR_OK; -} - // Callback for incoming tcp connections. STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { // err can be ERR_MEM to notify us that there was no memory for an incoming connection @@ -476,12 +465,9 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { if (++socket->incoming.connection.iput >= socket->incoming.connection.alloc) { socket->incoming.connection.iput = 0; } - if (socket->callback != MP_OBJ_NULL) { - // Schedule accept callback to be called when lwIP is done - // with processing this incoming connection on its side and - // is idle. - tcp_poll(newpcb, _lwip_tcp_accept_finished, 1); - } + + // Schedule user accept callback + exec_user_callback(socket); // Set the error callback to handle the case of a dropped connection before we // have a chance to take it off the accept queue. From f88cb8a51412d8570e473045adf09699664f553a Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 16:46:07 +1000 Subject: [PATCH 0234/1299] stm32/modmachine: Make RTC class available in machine module. This is a start to make a more consistent machine.RTC class across ports. The stm32 pyb.RTC class at least has the datetime() method which behaves the same as esp8266 and esp32, and with this patch the ntptime.py script now works with stm32. --- ports/stm32/modmachine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index a4ee47470b1dd..7ea14bdcd621a 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -384,8 +384,8 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, -#if 0 { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, +#if 0 { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, #endif #if MICROPY_PY_MACHINE_I2C From 3581deec816ff88a7dc2c0274b7c60b11e4ade34 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 16:50:02 +1000 Subject: [PATCH 0235/1299] stm32/boards/PYBD_SF2: Put mbedtls library code in external QSPI flash. mbedtls is large and self contained so is a good candidate to be in external XIP flash, to keep enough spare ROM in internal flash. --- ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index b6d3e08e30c76..554d34b4926f9 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -47,6 +47,8 @@ SECTIONS { .text_ext : { + . = ALIGN(4); + *lib/mbedtls/*(.text* .rodata*) . = ALIGN(512); *(.big_const*) . = ALIGN(4); From 9083166c4f943938afd160918f1be6dc31861557 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 23:36:43 +1000 Subject: [PATCH 0236/1299] lib/stm32lib: Update library for updated H7xx, new L0xx, new WBxx. And this library now includes the startup_stm32*.s files for each MCU. --- lib/stm32lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/stm32lib b/lib/stm32lib index 615329f1a61bd..668d7a9e54aea 160000 --- a/lib/stm32lib +++ b/lib/stm32lib @@ -1 +1 @@ -Subproject commit 615329f1a61bd0689bfb095cb3fd74865cca88ff +Subproject commit 668d7a9e54aea98f8fe8a858eac1d3daa80fa824 From 73e8b7e0e4a7c9f89094ffe7d93c6d897a86b67a Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 23:40:49 +1000 Subject: [PATCH 0237/1299] stm32: Update components to work with new H7xx HAL. --- ports/stm32/adc.c | 2 -- ports/stm32/boards/stm32h7xx_hal_conf_base.h | 1 + ports/stm32/mphalport.h | 5 ----- ports/stm32/stm32_it.c | 2 ++ ports/stm32/uart.c | 2 ++ ports/stm32/uart.h | 2 ++ ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 6 ++++++ 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 46fbbe73640a1..1215690333809 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -110,7 +110,6 @@ #define ADC_CAL1 ((uint16_t*)(0x1FF1E820)) #define ADC_CAL2 ((uint16_t*)(0x1FF1E840)) #define ADC_CAL_BITS (16) -#define ADC_CHANNEL_VBAT ADC_CHANNEL_VBAT_DIV4 #elif defined(STM32L4) @@ -247,7 +246,6 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.DMAContinuousRequests = DISABLE; #elif defined(STM32H7) adch->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - adch->Init.BoostMode = ENABLE; adch->Init.ScanConvMode = DISABLE; adch->Init.LowPowerAutoWait = DISABLE; adch->Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; diff --git a/ports/stm32/boards/stm32h7xx_hal_conf_base.h b/ports/stm32/boards/stm32h7xx_hal_conf_base.h index 334c6df4bdc2d..1d06be14fac2e 100644 --- a/ports/stm32/boards/stm32h7xx_hal_conf_base.h +++ b/ports/stm32/boards/stm32h7xx_hal_conf_base.h @@ -28,6 +28,7 @@ // Include various HAL modules for convenience #include "stm32h7xx_hal_dma.h" +#include "stm32h7xx_hal_mdma.h" #include "stm32h7xx_hal_adc.h" #include "stm32h7xx_hal_cortex.h" #include "stm32h7xx_hal_crc.h" diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index 0c163fbf85373..bd71adf77bd4a 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -63,13 +63,8 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { #define mp_hal_pin_input(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_output(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_open_drain(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 0) -#if defined(STM32H7) -#define mp_hal_pin_high(p) (((p)->gpio->BSRRL) = (p)->pin_mask) -#define mp_hal_pin_low(p) (((p)->gpio->BSRRH) = (p)->pin_mask) -#else #define mp_hal_pin_high(p) (((p)->gpio->BSRR) = (p)->pin_mask) #define mp_hal_pin_low(p) (((p)->gpio->BSRR) = ((p)->pin_mask << 16)) -#endif #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_read(p) (((p)->gpio->IDR >> (p)->pin) & 1) diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index a3740d59cd91e..fd3aea6c1c6ba 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -378,8 +378,10 @@ void OTG_FS_WKUP_IRQHandler(void) { OTG_CMD_WKUP_Handler(&pcd_fs_handle); + #if !defined(STM32H7) /* Clear EXTI pending Bit*/ __HAL_USB_FS_EXTI_CLEAR_FLAG(); + #endif IRQ_EXIT(OTG_FS_WKUP_IRQn); } diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 317dbe95b6c7c..3a21a0b31ebe4 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -40,6 +40,8 @@ #if defined(STM32F4) #define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE) +#elif defined(STM32H7) +#define UART_RXNE_IS_SET(uart) ((uart)->ISR & USART_ISR_RXNE_RXFNE) #else #define UART_RXNE_IS_SET(uart) ((uart)->ISR & USART_ISR_RXNE) #endif diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index 9b0d139588129..62676fb91be51 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -88,6 +88,8 @@ void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); static inline bool uart_tx_avail(pyb_uart_obj_t *self) { #if defined(STM32F4) return self->uartx->SR & USART_SR_TXE; + #elif defined(STM32H7) + return self->uartx->ISR & USART_ISR_TXE_TXFNF; #else return self->uartx->ISR & USART_ISR_TXE; #endif diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index d982fe8e6f6b5..627fb054c0f84 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -1129,6 +1129,9 @@ uint8_t USBD_HID_SetNAK(usbd_hid_state_t *hid) { // get USBx object from pdev (needed for USBx_OUTEP macro below) PCD_HandleTypeDef *hpcd = hid->usbd->pdev->pData; USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + #if defined(STM32H7) + uint32_t USBx_BASE = (uint32_t)USBx; + #endif // set NAK on HID OUT endpoint USBx_OUTEP(HID_OUT_EP_WITH_CDC)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK; return USBD_OK; @@ -1138,6 +1141,9 @@ uint8_t USBD_HID_ClearNAK(usbd_hid_state_t *hid) { // get USBx object from pdev (needed for USBx_OUTEP macro below) PCD_HandleTypeDef *hpcd = hid->usbd->pdev->pData; USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + #if defined(STM32H7) + uint32_t USBx_BASE = (uint32_t)USBx; + #endif // clear NAK on HID OUT endpoint USBx_OUTEP(HID_OUT_EP_WITH_CDC)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; return USBD_OK; From 241e57775359bc55738cb56b044ba4cc9056eba5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 23:41:33 +1000 Subject: [PATCH 0238/1299] stm32/Makefile: Remove Wno-attributes for ll_usb HAL file. This HAL file is now patched so it doesn't have these warnings. --- ports/stm32/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 153ea446262d0..45d4653dba7b2 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -319,7 +319,6 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ ) ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l4)) -$(BUILD)/$(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_ll_usb.o: CFLAGS += -Wno-attributes SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_sd.c \ ll_sdmmc.c \ From 6b6403ce76e11fd564d9bbe90f190c99fe4e4fa2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 23:42:36 +1000 Subject: [PATCH 0239/1299] stm32/Makefile: Use startup_stm32*.s file from stm32lib. This means that each MCU now gets a unique IRQ table, eg a specific one for STM32F405, STM32F411, etc rather than just STM32F4xx. --- ports/stm32/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 45d4653dba7b2..3967e631170d2 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -24,9 +24,11 @@ FROZEN_MPY_DIR ?= modules # include py core make definitions include $(TOP)/py/py.mk +MCU_SERIES_UPPER = $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') +CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]') + LD_DIR=boards CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include -MCU_SERIES_UPPER = $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') HAL_DIR=lib/stm32lib/STM32$(MCU_SERIES_UPPER)xx_HAL_Driver USBDEV_DIR=usbdev #USBHOST_DIR=usbhost @@ -40,7 +42,7 @@ DEVICE=0483:df11 STFLASH ?= st-flash OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg -STARTUP_FILE ?= boards/startup_stm32$(MCU_SERIES).o +STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o # Select the cross compile prefix CROSS_COMPILE ?= arm-none-eabi- @@ -576,7 +578,6 @@ GEN_PLLFREQTABLE_HDR = $(HEADER_BUILD)/pllfreqtable.h GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h -CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]') CMSIS_MCU_HDR = $(CMSIS_DIR)/$(CMSIS_MCU_LOWER).h modmachine.c: $(GEN_PLLFREQTABLE_HDR) From 7cf8285ac852c86d102fb85383e955f836222e69 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 23:44:17 +1000 Subject: [PATCH 0240/1299] stm32/boards: Remove startup_stm32*.s files now they are in stm32lib. --- ports/stm32/boards/startup_stm32f0.s | 303 --------- ports/stm32/boards/startup_stm32f4.s | 530 ---------------- ports/stm32/boards/startup_stm32f413xx.s | 580 ----------------- ports/stm32/boards/startup_stm32f7.s | 604 ------------------ ports/stm32/boards/startup_stm32h7.s | 763 ----------------------- ports/stm32/boards/startup_stm32l4.s | 549 ---------------- 6 files changed, 3329 deletions(-) delete mode 100644 ports/stm32/boards/startup_stm32f0.s delete mode 100644 ports/stm32/boards/startup_stm32f4.s delete mode 100644 ports/stm32/boards/startup_stm32f413xx.s delete mode 100644 ports/stm32/boards/startup_stm32f7.s delete mode 100644 ports/stm32/boards/startup_stm32h7.s delete mode 100644 ports/stm32/boards/startup_stm32l4.s diff --git a/ports/stm32/boards/startup_stm32f0.s b/ports/stm32/boards/startup_stm32f0.s deleted file mode 100644 index eb5c4961e017a..0000000000000 --- a/ports/stm32/boards/startup_stm32f0.s +++ /dev/null @@ -1,303 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32f091xc.s - * @author MCD Application Team - * @brief STM32F091xC devices vector table for GCC toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M0 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m0 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr r0, =_estack - mov sp, r0 /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - ldr r0, =_sdata - ldr r1, =_edata - ldr r2, =_sidata - movs r3, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r4, [r2, r3] - str r4, [r0, r3] - adds r3, r3, #4 - -LoopCopyDataInit: - adds r4, r0, r3 - cmp r4, r1 - bcc CopyDataInit - -/* Zero fill the bss segment. */ - ldr r2, =_sbss - ldr r4, =_ebss - movs r3, #0 - b LoopFillZerobss - -FillZerobss: - str r3, [r2] - adds r2, r2, #4 - -LoopFillZerobss: - cmp r2, r4 - bcc FillZerobss - -/* Call the clock system intitialization function.*/ - bl SystemInit -/* Call static constructors */ - /*bl __libc_init_array*/ -/* Call the application's entry point.*/ - bl main - -LoopForever: - b LoopForever - - -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * - * @param None - * @retval : None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M0. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word 0 - .word 0 - .word PendSV_Handler - .word SysTick_Handler - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_VDDIO2_IRQHandler /* PVD and VDDIO2 through EXTI Line detect */ - .word RTC_IRQHandler /* RTC through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_CRS_IRQHandler /* RCC and CRS */ - .word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */ - .word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */ - .word EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */ - .word TSC_IRQHandler /* TSC */ - .word DMA1_Ch1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler /* DMA1 Channel 2 and 3 & DMA2 Channel 1 and 2 */ - .word DMA1_Ch4_7_DMA2_Ch3_5_IRQHandler /* DMA1 Channel 4 to 7 & DMA2 Channel 3 to 5 */ - .word ADC1_COMP_IRQHandler /* ADC1, COMP1 and COMP2 */ - .word TIM1_BRK_UP_TRG_COM_IRQHandler /* TIM1 Break, Update, Trigger and Commutation */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC */ - .word TIM7_IRQHandler /* TIM7 */ - .word TIM14_IRQHandler /* TIM14 */ - .word TIM15_IRQHandler /* TIM15 */ - .word TIM16_IRQHandler /* TIM16 */ - .word TIM17_IRQHandler /* TIM17 */ - .word I2C1_IRQHandler /* I2C1 */ - .word I2C2_IRQHandler /* I2C2 */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_8_IRQHandler /* USART3, USART4, USART5, USART6, USART7, USART8 */ - .word CEC_CAN_IRQHandler /* CEC and CAN */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_VDDIO2_IRQHandler - .thumb_set PVD_VDDIO2_IRQHandler,Default_Handler - - .weak RTC_IRQHandler - .thumb_set RTC_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_CRS_IRQHandler - .thumb_set RCC_CRS_IRQHandler,Default_Handler - - .weak EXTI0_1_IRQHandler - .thumb_set EXTI0_1_IRQHandler,Default_Handler - - .weak EXTI2_3_IRQHandler - .thumb_set EXTI2_3_IRQHandler,Default_Handler - - .weak EXTI4_15_IRQHandler - .thumb_set EXTI4_15_IRQHandler,Default_Handler - - .weak TSC_IRQHandler - .thumb_set TSC_IRQHandler,Default_Handler - - .weak DMA1_Ch1_IRQHandler - .thumb_set DMA1_Ch1_IRQHandler,Default_Handler - - .weak DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler - .thumb_set DMA1_Ch2_3_DMA2_Ch1_2_IRQHandler,Default_Handler - - .weak DMA1_Ch4_7_DMA2_Ch3_5_IRQHandler - .thumb_set DMA1_Ch4_7_DMA2_Ch3_5_IRQHandler,Default_Handler - - .weak ADC1_COMP_IRQHandler - .thumb_set ADC1_COMP_IRQHandler,Default_Handler - - .weak TIM1_BRK_UP_TRG_COM_IRQHandler - .thumb_set TIM1_BRK_UP_TRG_COM_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak TIM14_IRQHandler - .thumb_set TIM14_IRQHandler,Default_Handler - - .weak TIM15_IRQHandler - .thumb_set TIM15_IRQHandler,Default_Handler - - .weak TIM16_IRQHandler - .thumb_set TIM16_IRQHandler,Default_Handler - - .weak TIM17_IRQHandler - .thumb_set TIM17_IRQHandler,Default_Handler - - .weak I2C1_IRQHandler - .thumb_set I2C1_IRQHandler,Default_Handler - - .weak I2C2_IRQHandler - .thumb_set I2C2_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_8_IRQHandler - .thumb_set USART3_8_IRQHandler,Default_Handler - - .weak CEC_CAN_IRQHandler - .thumb_set CEC_CAN_IRQHandler,Default_Handler - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ - diff --git a/ports/stm32/boards/startup_stm32f4.s b/ports/stm32/boards/startup_stm32f4.s deleted file mode 100644 index 3e29a79a5631d..0000000000000 --- a/ports/stm32/boards/startup_stm32f4.s +++ /dev/null @@ -1,530 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32.S - * @author MCD Application Team - * @version V2.0.0 - * @date 18-February-2014 - * @brief STM32Fxxxxx Devices vector table for Atollic TrueSTUDIO toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4/M7 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - /*bl __libc_init_array*/ -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M4/M7. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ - .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FSMC_IRQHandler /* FSMC */ - .word SDIO_IRQHandler /* SDIO */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* CRYP crypto */ - .word HASH_RNG_IRQHandler /* Hash and Rng */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler - .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler - .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM11_IRQHandler - .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FSMC_IRQHandler - .thumb_set FSMC_IRQHandler,Default_Handler - - .weak SDIO_IRQHandler - .thumb_set SDIO_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak ETH_IRQHandler - .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler - .thumb_set ETH_WKUP_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler - .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler - .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler - .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler - .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak HASH_RNG_IRQHandler - .thumb_set HASH_RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/boards/startup_stm32f413xx.s b/ports/stm32/boards/startup_stm32f413xx.s deleted file mode 100644 index 64108ad38d9a7..0000000000000 --- a/ports/stm32/boards/startup_stm32f413xx.s +++ /dev/null @@ -1,580 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32f413xx.s - * @author MCD Application Team - * @brief STM32F413xx Devices vector table for GCC based toolchains. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2017 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system intitialization function.*/ - bl SystemInit -/* Call static constructors */ - /*bl __libc_init_array*/ -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ - .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FSMC_IRQHandler /* FSMC */ - .word SDIO_IRQHandler /* SDIO */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6, DAC1 and DAC2 */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word DFSDM1_FLT0_IRQHandler /* DFSDM1 Filter0 */ - .word DFSDM1_FLT1_IRQHandler /* DFSDM1 Filter1 */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word CAN3_TX_IRQHandler /* CAN3 TX */ - .word CAN3_RX0_IRQHandler /* CAN3 RX0 */ - .word CAN3_RX1_IRQHandler /* CAN3 RX1 */ - .word CAN3_SCE_IRQHandler /* CAN3 SCE */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word RNG_IRQHandler /* RNG */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word SPI4_IRQHandler /* SPI4 */ - .word SPI5_IRQHandler /* SPI5 */ - .word 0 /* Reserved */ - .word SAI1_IRQHandler /* SAI1 */ - .word UART9_IRQHandler /* UART9 */ - .word UART10_IRQHandler /* UART10 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word QUADSPI_IRQHandler /* QuadSPI */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word FMPI2C1_EV_IRQHandler /* FMPI2C1 Event */ - .word FMPI2C1_ER_IRQHandler /* FMPI2C1 Error */ - .word LPTIM1_IRQHandler /* LPTIM1 */ - .word DFSDM2_FLT0_IRQHandler /* DFSDM2 Filter0 */ - .word DFSDM2_FLT1_IRQHandler /* DFSDM2 Filter1 */ - .word DFSDM2_FLT2_IRQHandler /* DFSDM2 Filter2 */ - .word DFSDM2_FLT3_IRQHandler /* DFSDM2 Filter3 */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler - .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler - .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM11_IRQHandler - .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FSMC_IRQHandler - .thumb_set FSMC_IRQHandler,Default_Handler - - .weak SDIO_IRQHandler - .thumb_set SDIO_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak DFSDM1_FLT0_IRQHandler - .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler - - .weak DFSDM1_FLT1_IRQHandler - .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak CAN3_TX_IRQHandler - .thumb_set CAN3_TX_IRQHandler,Default_Handler - - .weak CAN3_RX0_IRQHandler - .thumb_set CAN3_RX0_IRQHandler,Default_Handler - - .weak CAN3_RX1_IRQHandler - .thumb_set CAN3_RX1_IRQHandler,Default_Handler - - .weak CAN3_SCE_IRQHandler - .thumb_set CAN3_SCE_IRQHandler,Default_Handler - - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak SPI5_IRQHandler - .thumb_set SPI5_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak UART9_IRQHandler - .thumb_set UART9_IRQHandler,Default_Handler - - .weak UART10_IRQHandler - .thumb_set UART10_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak FMPI2C1_EV_IRQHandler - .thumb_set FMPI2C1_EV_IRQHandler,Default_Handler - - .weak FMPI2C1_ER_IRQHandler - .thumb_set FMPI2C1_ER_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler - - .weak DFSDM2_FLT0_IRQHandler - .thumb_set DFSDM2_FLT0_IRQHandler,Default_Handler - - .weak DFSDM2_FLT1_IRQHandler - .thumb_set DFSDM2_FLT1_IRQHandler,Default_Handler - - .weak DFSDM2_FLT2_IRQHandler - .thumb_set DFSDM2_FLT2_IRQHandler,Default_Handler - - .weak DFSDM2_FLT3_IRQHandler - .thumb_set DFSDM2_FLT3_IRQHandler,Default_Handler -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/boards/startup_stm32f7.s b/ports/stm32/boards/startup_stm32f7.s deleted file mode 100644 index 633ba01e9313d..0000000000000 --- a/ports/stm32/boards/startup_stm32f7.s +++ /dev/null @@ -1,604 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32.S - * @author MCD Application Team - * @version V2.0.0 - * @date 18-February-2014 - * @brief STM32Fxxxxx Devices vector table for Atollic TrueSTUDIO toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4/M7 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2014 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m7 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - /*bl __libc_init_array*/ -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M4/M7. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_IRQHandler /* PVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ - .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ - .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FMC_IRQHandler /* FMC */ - .word SDMMC1_IRQHandler /* SDMMC1 */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SCE_IRQHandler /* CAN2 SCE */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* CRYP crypto */ - .word HASH_RNG_IRQHandler /* Hash and Rng */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word SPI4_IRQHandler /* SPI4 */ - .word SPI5_IRQHandler /* SPI5 */ - .word SPI6_IRQHandler /* SPI6 */ - .word SAI1_IRQHandler /* SAI1 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word DMA2D_IRQHandler /* DMA2D */ - .word SAI2_IRQHandler /* SAI2 */ - .word QUADSPI_IRQHandler /* QUADSPI */ - .word LPTIM1_IRQHandler /* LPTIM1 */ - .word CEC_IRQHandler /* HDMI_CEC */ - .word I2C4_EV_IRQHandler /* I2C4 Event */ - .word I2C4_ER_IRQHandler /* I2C4 Error */ - .word SPDIF_RX_IRQHandler /* SPDIF_RX */ - .word DSIHOST_IRQHandler /* DSI host */ - .word DFSDM1_FLT0_IRQHandler /* DFSDM1 filter 0 */ - .word DFSDM1_FLT1_IRQHandler /* DFSDM1 filter 1 */ - .word DFSDM1_FLT2_IRQHandler /* DFSDM1 filter 2 */ - .word DFSDM1_FLT3_IRQHandler /* DFSDM1 filter 3 */ - .word SDMMC2_IRQHandler /* SDMMC2 */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM9_IRQHandler - .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM10_IRQHandler - .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM11_IRQHandler - .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FMC_IRQHandler - .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDMMC1_IRQHandler - .thumb_set SDMMC1_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak ETH_IRQHandler - .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler - .thumb_set ETH_WKUP_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler - .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler - .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler - .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler - .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak HASH_RNG_IRQHandler - .thumb_set HASH_RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak SPI5_IRQHandler - .thumb_set SPI5_IRQHandler,Default_Handler - - .weak SPI6_IRQHandler - .thumb_set SPI6_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak DMA2D_IRQHandler - .thumb_set DMA2D_IRQHandler,Default_Handler - - .weak SAI2_IRQHandler - .thumb_set SAI2_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler - - .weak CEC_IRQHandler - .thumb_set CEC_IRQHandler,Default_Handler - - .weak I2C4_EV_IRQHandler - .thumb_set I2C4_EV_IRQHandler,Default_Handler - - .weak I2C4_ER_IRQHandler - .thumb_set I2C4_ER_IRQHandler,Default_Handler - - .weak SPDIF_RX_IRQHandler - .thumb_set SPDIF_RX_IRQHandler,Default_Handler - - .weak DSIHOST_IRQHandler - .thumb_set DSIHOST_IRQHandler,Default_Handler - - .weak DFSDM1_FLT0_IRQHandler - .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler - - .weak DFSDM1_FLT1_IRQHandler - .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler - - .weak DFSDM1_FLT2_IRQHandler - .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler - - .weak DFSDM1_FLT3_IRQHandler - .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler - - .weak SDMMC2_IRQHandler - .thumb_set SDMMC2_IRQHandler,Default_Handler - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/boards/startup_stm32h7.s b/ports/stm32/boards/startup_stm32h7.s deleted file mode 100644 index 53d46205fd692..0000000000000 --- a/ports/stm32/boards/startup_stm32h7.s +++ /dev/null @@ -1,763 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32h743xx.s - * @author MCD Application Team - * @version V1.2.0 - * @date 29-December-2017 - * @brief STM32H743xx Devices vector table for GCC based toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2017 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m7 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system intitialization function.*/ - bl SystemInit -/* Call static constructors */ -/* bl __libc_init_array */ -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_AVD_IRQHandler /* PVD/AVD through EXTI Line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ - .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ - .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ - .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ - .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ - .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ - .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ - .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ - .word FDCAN1_IT0_IRQHandler /* FDCAN1 interrupt line 0 */ - .word FDCAN2_IT0_IRQHandler /* FDCAN2 interrupt line 0 */ - .word FDCAN1_IT1_IRQHandler /* FDCAN1 interrupt line 1 */ - .word FDCAN2_IT1_IRQHandler /* FDCAN2 interrupt line 1 */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_IRQHandler /* TIM1 Break interrupt */ - .word TIM1_UP_IRQHandler /* TIM1 Update interrupt */ - .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation interrupt */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word 0 /* Reserved */ - .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ - .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ - .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ - .word FMC_IRQHandler /* FMC */ - .word SDMMC1_IRQHandler /* SDMMC1 */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ - .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ - .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ - .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ - .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ - .word ETH_IRQHandler /* Ethernet */ - .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ - .word FDCAN_CAL_IRQHandler /* FDCAN calibration unit interrupt*/ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ - .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ - .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ - .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ - .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ - .word OTG_HS_IRQHandler /* USB OTG HS */ - .word DCMI_IRQHandler /* DCMI */ - .word 0 /* Reserved */ - .word RNG_IRQHandler /* Rng */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word SPI4_IRQHandler /* SPI4 */ - .word SPI5_IRQHandler /* SPI5 */ - .word SPI6_IRQHandler /* SPI6 */ - .word SAI1_IRQHandler /* SAI1 */ - .word LTDC_IRQHandler /* LTDC */ - .word LTDC_ER_IRQHandler /* LTDC error */ - .word DMA2D_IRQHandler /* DMA2D */ - .word SAI2_IRQHandler /* SAI2 */ - .word QUADSPI_IRQHandler /* QUADSPI */ - .word LPTIM1_IRQHandler /* LPTIM1 */ - .word CEC_IRQHandler /* HDMI_CEC */ - .word I2C4_EV_IRQHandler /* I2C4 Event */ - .word I2C4_ER_IRQHandler /* I2C4 Error */ - .word SPDIF_RX_IRQHandler /* SPDIF_RX */ - .word OTG_FS_EP1_OUT_IRQHandler /* USB OTG FS End Point 1 Out */ - .word OTG_FS_EP1_IN_IRQHandler /* USB OTG FS End Point 1 In */ - .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMAMUX1_OVR_IRQHandler /* DMAMUX1 Overrun interrupt */ - .word HRTIM1_Master_IRQHandler /* HRTIM Master Timer global Interrupt */ - .word HRTIM1_TIMA_IRQHandler /* HRTIM Timer A global Interrupt */ - .word HRTIM1_TIMB_IRQHandler /* HRTIM Timer B global Interrupt */ - .word HRTIM1_TIMC_IRQHandler /* HRTIM Timer C global Interrupt */ - .word HRTIM1_TIMD_IRQHandler /* HRTIM Timer D global Interrupt */ - .word HRTIM1_TIME_IRQHandler /* HRTIM Timer E global Interrupt */ - .word HRTIM1_FLT_IRQHandler /* HRTIM Fault global Interrupt */ - .word DFSDM1_FLT0_IRQHandler /* DFSDM Filter0 Interrupt */ - .word DFSDM1_FLT1_IRQHandler /* DFSDM Filter1 Interrupt */ - .word DFSDM1_FLT2_IRQHandler /* DFSDM Filter2 Interrupt */ - .word DFSDM1_FLT3_IRQHandler /* DFSDM Filter3 Interrupt */ - .word SAI3_IRQHandler /* SAI3 global Interrupt */ - .word SWPMI1_IRQHandler /* Serial Wire Interface 1 global interrupt */ - .word TIM15_IRQHandler /* TIM15 global Interrupt */ - .word TIM16_IRQHandler /* TIM16 global Interrupt */ - .word TIM17_IRQHandler /* TIM17 global Interrupt */ - .word MDIOS_WKUP_IRQHandler /* MDIOS Wakeup Interrupt */ - .word MDIOS_IRQHandler /* MDIOS global Interrupt */ - .word JPEG_IRQHandler /* JPEG global Interrupt */ - .word MDMA_IRQHandler /* MDMA global Interrupt */ - .word 0 /* Reserved */ - .word SDMMC2_IRQHandler /* SDMMC2 global Interrupt */ - .word HSEM1_IRQHandler /* HSEM1 global Interrupt */ - .word 0 /* Reserved */ - .word ADC3_IRQHandler /* ADC3 global Interrupt */ - .word DMAMUX2_OVR_IRQHandler /* DMAMUX Overrun interrupt */ - .word BDMA_Channel0_IRQHandler /* BDMA Channel 0 global Interrupt */ - .word BDMA_Channel1_IRQHandler /* BDMA Channel 1 global Interrupt */ - .word BDMA_Channel2_IRQHandler /* BDMA Channel 2 global Interrupt */ - .word BDMA_Channel3_IRQHandler /* BDMA Channel 3 global Interrupt */ - .word BDMA_Channel4_IRQHandler /* BDMA Channel 4 global Interrupt */ - .word BDMA_Channel5_IRQHandler /* BDMA Channel 5 global Interrupt */ - .word BDMA_Channel6_IRQHandler /* BDMA Channel 6 global Interrupt */ - .word BDMA_Channel7_IRQHandler /* BDMA Channel 7 global Interrupt */ - .word COMP1_IRQHandler /* COMP1 global Interrupt */ - .word LPTIM2_IRQHandler /* LP TIM2 global interrupt */ - .word LPTIM3_IRQHandler /* LP TIM3 global interrupt */ - .word LPTIM4_IRQHandler /* LP TIM4 global interrupt */ - .word LPTIM5_IRQHandler /* LP TIM5 global interrupt */ - .word LPUART1_IRQHandler /* LP UART1 interrupt */ - .word 0 /* Reserved */ - .word CRS_IRQHandler /* Clock Recovery Global Interrupt */ - .word 0 /* Reserved */ - .word SAI4_IRQHandler /* SAI4 global interrupt */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word WAKEUP_PIN_IRQHandler /* Interrupt for all 6 wake-up pins */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_AVD_IRQHandler - .thumb_set PVD_AVD_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Stream0_IRQHandler - .thumb_set DMA1_Stream0_IRQHandler,Default_Handler - - .weak DMA1_Stream1_IRQHandler - .thumb_set DMA1_Stream1_IRQHandler,Default_Handler - - .weak DMA1_Stream2_IRQHandler - .thumb_set DMA1_Stream2_IRQHandler,Default_Handler - - .weak DMA1_Stream3_IRQHandler - .thumb_set DMA1_Stream3_IRQHandler,Default_Handler - - .weak DMA1_Stream4_IRQHandler - .thumb_set DMA1_Stream4_IRQHandler,Default_Handler - - .weak DMA1_Stream5_IRQHandler - .thumb_set DMA1_Stream5_IRQHandler,Default_Handler - - .weak DMA1_Stream6_IRQHandler - .thumb_set DMA1_Stream6_IRQHandler,Default_Handler - - .weak ADC_IRQHandler - .thumb_set ADC_IRQHandler,Default_Handler - - .weak FDCAN1_IT0_IRQHandler - .thumb_set FDCAN1_IT0_IRQHandler,Default_Handler - - .weak FDCAN2_IT0_IRQHandler - .thumb_set FDCAN2_IT0_IRQHandler,Default_Handler - - .weak FDCAN1_IT1_IRQHandler - .thumb_set FDCAN1_IT1_IRQHandler,Default_Handler - - .weak FDCAN2_IT1_IRQHandler - .thumb_set FDCAN2_IT1_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_IRQHandler - .thumb_set TIM1_BRK_IRQHandler,Default_Handler - - .weak TIM1_UP_IRQHandler - .thumb_set TIM1_UP_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_IRQHandler - .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak TIM8_BRK_TIM12_IRQHandler - .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler - - .weak TIM8_UP_TIM13_IRQHandler - .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_TIM14_IRQHandler - .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak DMA1_Stream7_IRQHandler - .thumb_set DMA1_Stream7_IRQHandler,Default_Handler - - .weak FMC_IRQHandler - .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDMMC1_IRQHandler - .thumb_set SDMMC1_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Stream0_IRQHandler - .thumb_set DMA2_Stream0_IRQHandler,Default_Handler - - .weak DMA2_Stream1_IRQHandler - .thumb_set DMA2_Stream1_IRQHandler,Default_Handler - - .weak DMA2_Stream2_IRQHandler - .thumb_set DMA2_Stream2_IRQHandler,Default_Handler - - .weak DMA2_Stream3_IRQHandler - .thumb_set DMA2_Stream3_IRQHandler,Default_Handler - - .weak DMA2_Stream4_IRQHandler - .thumb_set DMA2_Stream4_IRQHandler,Default_Handler - - .weak ETH_IRQHandler - .thumb_set ETH_IRQHandler,Default_Handler - - .weak ETH_WKUP_IRQHandler - .thumb_set ETH_WKUP_IRQHandler,Default_Handler - - .weak FDCAN_CAL_IRQHandler - .thumb_set FDCAN_CAL_IRQHandler,Default_Handler - - .weak DMA2_Stream5_IRQHandler - .thumb_set DMA2_Stream5_IRQHandler,Default_Handler - - .weak DMA2_Stream6_IRQHandler - .thumb_set DMA2_Stream6_IRQHandler,Default_Handler - - .weak DMA2_Stream7_IRQHandler - .thumb_set DMA2_Stream7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_OUT_IRQHandler - .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_HS_EP1_IN_IRQHandler - .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_HS_WKUP_IRQHandler - .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler - - .weak OTG_HS_IRQHandler - .thumb_set OTG_HS_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak SPI5_IRQHandler - .thumb_set SPI5_IRQHandler,Default_Handler - - .weak SPI6_IRQHandler - .thumb_set SPI6_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak LTDC_IRQHandler - .thumb_set LTDC_IRQHandler,Default_Handler - - .weak LTDC_ER_IRQHandler - .thumb_set LTDC_ER_IRQHandler,Default_Handler - - .weak DMA2D_IRQHandler - .thumb_set DMA2D_IRQHandler,Default_Handler - - .weak SAI2_IRQHandler - .thumb_set SAI2_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler - - .weak CEC_IRQHandler - .thumb_set CEC_IRQHandler,Default_Handler - - .weak I2C4_EV_IRQHandler - .thumb_set I2C4_EV_IRQHandler,Default_Handler - - .weak I2C4_ER_IRQHandler - .thumb_set I2C4_ER_IRQHandler,Default_Handler - - .weak SPDIF_RX_IRQHandler - .thumb_set SPDIF_RX_IRQHandler,Default_Handler - - .weak OTG_FS_EP1_OUT_IRQHandler - .thumb_set OTG_FS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTG_FS_EP1_IN_IRQHandler - .thumb_set OTG_FS_EP1_IN_IRQHandler,Default_Handler - - .weak OTG_FS_WKUP_IRQHandler - .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMAMUX1_OVR_IRQHandler - .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler - - .weak HRTIM1_Master_IRQHandler - .thumb_set HRTIM1_Master_IRQHandler,Default_Handler - - .weak HRTIM1_TIMA_IRQHandler - .thumb_set HRTIM1_TIMA_IRQHandler,Default_Handler - - .weak HRTIM1_TIMB_IRQHandler - .thumb_set HRTIM1_TIMB_IRQHandler,Default_Handler - - .weak HRTIM1_TIMC_IRQHandler - .thumb_set HRTIM1_TIMC_IRQHandler,Default_Handler - - .weak HRTIM1_TIMD_IRQHandler - .thumb_set HRTIM1_TIMD_IRQHandler,Default_Handler - - .weak HRTIM1_TIME_IRQHandler - .thumb_set HRTIM1_TIME_IRQHandler,Default_Handler - - .weak HRTIM1_FLT_IRQHandler - .thumb_set HRTIM1_FLT_IRQHandler,Default_Handler - - .weak DFSDM1_FLT0_IRQHandler - .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler - - .weak DFSDM1_FLT1_IRQHandler - .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler - - .weak DFSDM1_FLT2_IRQHandler - .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler - - .weak DFSDM1_FLT3_IRQHandler - .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler - - .weak SAI3_IRQHandler - .thumb_set SAI3_IRQHandler,Default_Handler - - .weak SWPMI1_IRQHandler - .thumb_set SWPMI1_IRQHandler,Default_Handler - - .weak TIM15_IRQHandler - .thumb_set TIM15_IRQHandler,Default_Handler - - .weak TIM16_IRQHandler - .thumb_set TIM16_IRQHandler,Default_Handler - - .weak TIM17_IRQHandler - .thumb_set TIM17_IRQHandler,Default_Handler - - .weak MDIOS_WKUP_IRQHandler - .thumb_set MDIOS_WKUP_IRQHandler,Default_Handler - - .weak MDIOS_IRQHandler - .thumb_set MDIOS_IRQHandler,Default_Handler - - .weak JPEG_IRQHandler - .thumb_set JPEG_IRQHandler,Default_Handler - - .weak MDMA_IRQHandler - .thumb_set MDMA_IRQHandler,Default_Handler - - .weak SDMMC2_IRQHandler - .thumb_set SDMMC2_IRQHandler,Default_Handler - - .weak HSEM1_IRQHandler - .thumb_set HSEM1_IRQHandler,Default_Handler - - .weak ADC3_IRQHandler - .thumb_set ADC3_IRQHandler,Default_Handler - - .weak DMAMUX2_OVR_IRQHandler - .thumb_set DMAMUX2_OVR_IRQHandler,Default_Handler - - .weak BDMA_Channel0_IRQHandler - .thumb_set BDMA_Channel0_IRQHandler,Default_Handler - - .weak BDMA_Channel1_IRQHandler - .thumb_set BDMA_Channel1_IRQHandler,Default_Handler - - .weak BDMA_Channel2_IRQHandler - .thumb_set BDMA_Channel2_IRQHandler,Default_Handler - - .weak BDMA_Channel3_IRQHandler - .thumb_set BDMA_Channel3_IRQHandler,Default_Handler - - .weak BDMA_Channel4_IRQHandler - .thumb_set BDMA_Channel4_IRQHandler,Default_Handler - - .weak BDMA_Channel5_IRQHandler - .thumb_set BDMA_Channel5_IRQHandler,Default_Handler - - .weak BDMA_Channel6_IRQHandler - .thumb_set BDMA_Channel6_IRQHandler,Default_Handler - - .weak BDMA_Channel7_IRQHandler - .thumb_set BDMA_Channel7_IRQHandler,Default_Handler - - .weak COMP1_IRQHandler - .thumb_set COMP1_IRQHandler,Default_Handler - - .weak LPTIM2_IRQHandler - .thumb_set LPTIM2_IRQHandler,Default_Handler - - .weak LPTIM3_IRQHandler - .thumb_set LPTIM3_IRQHandler,Default_Handler - - .weak LPTIM4_IRQHandler - .thumb_set LPTIM4_IRQHandler,Default_Handler - - .weak LPTIM5_IRQHandler - .thumb_set LPTIM5_IRQHandler,Default_Handler - - .weak LPUART1_IRQHandler - .thumb_set LPUART1_IRQHandler,Default_Handler - - .weak CRS_IRQHandler - .thumb_set CRS_IRQHandler,Default_Handler - - .weak SAI4_IRQHandler - .thumb_set SAI4_IRQHandler,Default_Handler - - .weak WAKEUP_PIN_IRQHandler - .thumb_set WAKEUP_PIN_IRQHandler,Default_Handler - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ - diff --git a/ports/stm32/boards/startup_stm32l4.s b/ports/stm32/boards/startup_stm32l4.s deleted file mode 100644 index 3225723ff5cfb..0000000000000 --- a/ports/stm32/boards/startup_stm32l4.s +++ /dev/null @@ -1,549 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32l496xx.s - * @author MCD Application Team - * @brief STM32L496xx devices vector table GCC toolchain. - * This module performs: - * - Set the initial SP - * - Set the initial PC == Reset_Handler, - * - Set the vector table entries with the exceptions ISR address, - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M4 processor is in Thread mode, - * priority is Privileged, and the Stack is set to Main. - * Taken from STM32L4 template code for stm32l496 in STM32Cube_FW_L4_V1.11.0 - ****************************************************************************** - * @attention - * - *

© COPYRIGHT 2017 STMicroelectronics

- * - * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.st.com/software_license_agreement_liberty_v2 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -.equ BootRAM, 0xF1E0F85F -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - ldr sp, =_estack /* set stack pointer */ - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - /*bl __libc_init_array*/ -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex-M4. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDG_IRQHandler /* Window WatchDog */ - .word PVD_PVM_IRQHandler /* PVD and PVM through EXTI line detection */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ - .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ - .word FLASH_IRQHandler /* FLASH */ - .word RCC_IRQHandler /* RCC */ - .word EXTI0_IRQHandler /* EXTI Line0 */ - .word EXTI1_IRQHandler /* EXTI Line1 */ - .word EXTI2_IRQHandler /* EXTI Line2 */ - .word EXTI3_IRQHandler /* EXTI Line3 */ - .word EXTI4_IRQHandler /* EXTI Line4 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word ADC1_2_IRQHandler /* ADC1 and ADC2 */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SCE_IRQHandler /* CAN1 SCE */ - .word EXTI9_5_IRQHandler /* External Line[9:5]s */ - .word TIM1_BRK_TIM15_IRQHandler /* TIM1 Break and TIM15 */ - .word TIM1_UP_TIM16_IRQHandler /* TIM1 Update and TIM16 */ - .word TIM1_TRG_COM_TIM17_IRQHandler /* TIM1 Trigger and Commutation and TIM17 */ - .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ - .word TIM2_IRQHandler /* TIM2 */ - .word TIM3_IRQHandler /* TIM3 */ - .word TIM4_IRQHandler /* TIM4 */ - .word I2C1_EV_IRQHandler /* I2C1 Event */ - .word I2C1_ER_IRQHandler /* I2C1 Error */ - .word I2C2_EV_IRQHandler /* I2C2 Event */ - .word I2C2_ER_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXTI15_10_IRQHandler /* External Line[15:10]s */ - .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ - .word DFSDM1_FLT3_IRQHandler /* Digital filter 3 for sigma delta modulator */ - .word TIM8_BRK_IRQHandler /* TIM8 Break */ - .word TIM8_UP_IRQHandler /* TIM8 Update */ - .word TIM8_TRG_COM_IRQHandler /* TIM8 Trigger and Commutation */ - .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ - .word ADC3_IRQHandler /* ADC3 global interrupt */ - .word FMC_IRQHandler /* FMC */ - .word SDMMC1_IRQHandler /* SDMMC1 */ - .word TIM5_IRQHandler /* TIM5 */ - .word SPI3_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ - .word TIM7_IRQHandler /* TIM7 */ - .word DMA2_Channel1_IRQHandler /* DMA2 Channel 1 */ - .word DMA2_Channel2_IRQHandler /* DMA2 Channel 2 */ - .word DMA2_Channel3_IRQHandler /* DMA2 Channel 3 */ - .word DMA2_Channel4_IRQHandler /* DMA2 Channel 4 */ - .word DMA2_Channel5_IRQHandler /* DMA2 Channel 5 */ - .word DFSDM1_FLT0_IRQHandler /* Digital filter 0 for sigma delta modulator */ - .word DFSDM1_FLT1_IRQHandler /* Digital filter 1 for sigma delta modulator */ - .word DFSDM1_FLT2_IRQHandler /* Digital filter 2 for sigma delta modulator */ - .word COMP_IRQHandler /* Comporator thru EXTI line */ - .word LPTIM1_IRQHandler /* Low power timer 1 */ - .word LPTIM2_IRQHandler /* Low power timer 2 */ - .word OTG_FS_IRQHandler /* USB OTG FS */ - .word DMA2_Channel6_IRQHandler /* DMA2 Channel 6 */ - .word DMA2_Channel7_IRQHandler /* DMA2 Channel 7 */ - .word LPUART1_IRQHandler /* Low power UART */ - .word QUADSPI_IRQHandler /* Quad SPI */ - .word I2C3_EV_IRQHandler /* I2C3 event */ - .word I2C3_ER_IRQHandler /* I2C3 error */ - .word SAI1_IRQHandler /* Serial audio interface 1 */ - .word SAI2_IRQHandler /* Serial audio interface 2 */ - .word SWPMI1_IRQHandler /* Single wire protocole 1 */ - .word TSC_IRQHandler /* Touch sensig controller */ - .word LCD_IRQHandler /* LCD */ - .word 0 /* CRYP crypto */ - .word RNG_IRQHandler /* Random number generator */ - .word FPU_IRQHandler /* FPU */ - /* Following Handlers are only used on L496/4A6xx devices */ - .word CRS_IRQHandler /* HASH and CRS interrupt */ - .word I2C4_EV_IRQHandler /* I2C4 event interrupt */ - .word I2C4_ER_IRQHandler /* I2C4 error interrupt */ - .word DCMI_IRQHandler /* DCMI global interrupt */ - .word CAN2_TX_IRQHandler /* CAN2 TX interrupt */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 interrupt */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 interrupt */ - .word CAN2_SCE_IRQHandler /* CAN SCE interrupt */ - .word DMA2D_IRQHandler /* DMA2D global interrupt */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_PVM_IRQHandler - .thumb_set PVD_PVM_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak RTC_WKUP_IRQHandler - .thumb_set RTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_2_IRQHandler - .thumb_set ADC1_2_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_TIM15_IRQHandler - .thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler - - .weak TIM1_UP_TIM16_IRQHandler - .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_TIM17_IRQHandler - .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak DFSDM1_FLT3_IRQHandler - .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler - - .weak TIM8_BRK_IRQHandler - .thumb_set TIM8_BRK_IRQHandler,Default_Handler - - .weak TIM8_UP_IRQHandler - .thumb_set TIM8_UP_IRQHandler,Default_Handler - - .weak TIM8_TRG_COM_IRQHandler - .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler - - .weak TIM8_CC_IRQHandler - .thumb_set TIM8_CC_IRQHandler,Default_Handler - - .weak ADC3_IRQHandler - .thumb_set ADC3_IRQHandler,Default_Handler - - .weak FMC_IRQHandler - .thumb_set FMC_IRQHandler,Default_Handler - - .weak SDMMC1_IRQHandler - .thumb_set SDMMC1_IRQHandler,Default_Handler - - .weak TIM5_IRQHandler - .thumb_set TIM5_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TIM6_DAC_IRQHandler - .thumb_set TIM6_DAC_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_IRQHandler - .thumb_set DMA2_Channel4_IRQHandler,Default_Handler - - .weak DMA2_Channel5_IRQHandler - .thumb_set DMA2_Channel5_IRQHandler,Default_Handler - - .weak DFSDM1_FLT0_IRQHandler - .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler - - .weak DFSDM1_FLT1_IRQHandler - .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler - - .weak DFSDM1_FLT2_IRQHandler - .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler - - .weak COMP_IRQHandler - .thumb_set COMP_IRQHandler,Default_Handler - - .weak LPTIM1_IRQHandler - .thumb_set LPTIM1_IRQHandler,Default_Handler - - .weak LPTIM2_IRQHandler - .thumb_set LPTIM2_IRQHandler,Default_Handler - - .weak OTG_FS_IRQHandler - .thumb_set OTG_FS_IRQHandler,Default_Handler - - .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - - .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler - - .weak LPUART1_IRQHandler - .thumb_set LPUART1_IRQHandler,Default_Handler - - .weak QUADSPI_IRQHandler - .thumb_set QUADSPI_IRQHandler,Default_Handler - - .weak I2C3_EV_IRQHandler - .thumb_set I2C3_EV_IRQHandler,Default_Handler - - .weak I2C3_ER_IRQHandler - .thumb_set I2C3_ER_IRQHandler,Default_Handler - - .weak SAI1_IRQHandler - .thumb_set SAI1_IRQHandler,Default_Handler - - .weak SAI2_IRQHandler - .thumb_set SAI2_IRQHandler,Default_Handler - - .weak SWPMI1_IRQHandler - .thumb_set SWPMI1_IRQHandler,Default_Handler - - .weak TSC_IRQHandler - .thumb_set TSC_IRQHandler,Default_Handler - - .weak LCD_IRQHandler - .thumb_set LCD_IRQHandler,Default_Handler - - .weak RNG_IRQHandler - .thumb_set RNG_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak CRS_IRQHandler - .thumb_set CRS_IRQHandler,Default_Handler - - .weak I2C4_EV_IRQHandler - .thumb_set I2C4_EV_IRQHandler,Default_Handler - - .weak I2C4_ER_IRQHandler - .thumb_set I2C4_ER_IRQHandler,Default_Handler - - .weak DCMI_IRQHandler - .thumb_set DCMI_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler,Default_Handler - - .weak CAN2_SCE_IRQHandler - .thumb_set CAN2_SCE_IRQHandler,Default_Handler - - .weak DMA2D_IRQHandler - .thumb_set DMA2D_IRQHandler,Default_Handler -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 592f68449d8261f978a8d0198f9eaf9bc76927d3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 3 Jul 2019 23:49:49 +1000 Subject: [PATCH 0241/1299] stm32/mpu: Include MPU functions when ETH is enabled. --- ports/stm32/mpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/mpu.h b/ports/stm32/mpu.h index 2541d86bfb41b..1efe93a68b6e0 100644 --- a/ports/stm32/mpu.h +++ b/ports/stm32/mpu.h @@ -26,7 +26,7 @@ #ifndef MICROPY_INCLUDED_STM32_MPU_H #define MICROPY_INCLUDED_STM32_MPU_H -#if defined(STM32F7) || defined(STM32H7) +#if defined(STM32F7) || defined(STM32H7) || defined(MICROPY_HW_ETH_MDC) #define MPU_REGION_ETH (MPU_REGION_NUMBER0) #define MPU_REGION_QSPI1 (MPU_REGION_NUMBER1) From 1b79484ee3bfdb7cbd68a17effe60407580398c2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Jul 2019 10:36:23 +1000 Subject: [PATCH 0242/1299] lib/lwip: Update lwIP to v2.1.2, tag STABLE-2_1_2_RELEASE. --- lib/lwip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lwip b/lib/lwip index 92f23d6ca0971..159e31b689577 160000 --- a/lib/lwip +++ b/lib/lwip @@ -1 +1 @@ -Subproject commit 92f23d6ca0971a32f2085b9480e738d34174417b +Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10 From 04da8864e5113e8ef8d4b017bb277b145cfcf34f Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Jul 2019 10:36:51 +1000 Subject: [PATCH 0243/1299] stm32/lwip_inc: Define LWIP_NO_CTYPE_H=1 to use lwIP ctype funcs. --- ports/stm32/lwip_inc/arch/cc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/lwip_inc/arch/cc.h b/ports/stm32/lwip_inc/arch/cc.h index 635b1c805651c..fc5230ef723ea 100644 --- a/ports/stm32/lwip_inc/arch/cc.h +++ b/ports/stm32/lwip_inc/arch/cc.h @@ -5,4 +5,6 @@ #define LWIP_PLATFORM_DIAG(x) #define LWIP_PLATFORM_ASSERT(x) { assert(1); } +#define LWIP_NO_CTYPE_H 1 + #endif // MICROPY_INCLUDED_STM32_LWIP_ARCH_CC_H From afb2e9dd942a77125d4447a96def5be48fee19af Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Jul 2019 10:49:51 +1000 Subject: [PATCH 0244/1299] stm32/modmachine: Disable IRQs before entering bootloader. To make sure that the code that enters the bootloader is not interrupted. --- ports/stm32/modmachine.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 7ea14bdcd621a..ba0ee284713bf 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -257,6 +257,8 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) storage_flush(); #endif + __disable_irq(); + #if MICROPY_HW_USES_BOOTLOADER if (n_args == 0 || !mp_obj_is_true(args[0])) { // By default, with no args given, we enter the custom bootloader (mboot) From 1cd2bc066de7cfec778631d99fe64d29b093ba80 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Jul 2019 11:03:10 +1000 Subject: [PATCH 0245/1299] stm32/boards/PYBD_SFx: Configure EN_3V3 pin as output on boot. But leave it turned off, the application must turn it on if/when needed. --- ports/stm32/boards/PYBD_SF2/board_init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/board_init.c b/ports/stm32/boards/PYBD_SF2/board_init.c index 8438b82317631..a8cf10f3a57d8 100644 --- a/ports/stm32/boards/PYBD_SF2/board_init.c +++ b/ports/stm32/boards/PYBD_SF2/board_init.c @@ -33,6 +33,9 @@ void mboot_board_early_init(void) { } void board_early_init(void) { + // Configure EN_3V3 as an output pin, but keep it turned off + mp_hal_pin_config(pyb_pin_EN_3V3, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); + // Explicitly init SPI2 because it's not enabled as a block device spi_bdev_ioctl(&spi_bdev2, BDEV_IOCTL_INIT, (uint32_t)&spiflash2_config); } From 7f33f158b9212846b94c737793da4df71825df48 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Jul 2019 11:10:54 +1000 Subject: [PATCH 0246/1299] stm32/sdcard: Add hook for a board to power on SD/MMC. --- ports/stm32/sdcard.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 8ffba0b4c5c9d..0cb09b8189af4 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -304,6 +304,10 @@ bool sdcard_power_on(void) { return true; } + #ifdef MICROPY_BOARD_SDCARD_POWER + MICROPY_BOARD_SDCARD_POWER + #endif + HAL_StatusTypeDef status = HAL_ERROR; switch (pyb_sdmmc_flags) { #if MICROPY_HW_ENABLE_SDCARD From c1a8c7fc0985f1322d76e7b149bdb54535b457d2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Jul 2019 11:11:11 +1000 Subject: [PATCH 0247/1299] stm32/boards/PYBD_SFx: Automatically turn on EN_3V3 when powering SD/MMC --- ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index a46b5ca5bc7a9..215b3f40165e0 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -44,6 +44,7 @@ #define MICROPY_BOARD_ENTER_STOP board_sleep(1); #define MICROPY_BOARD_LEAVE_STOP board_sleep(0); #define MICROPY_BOARD_ENTER_STANDBY board_sleep(1); +#define MICROPY_BOARD_SDCARD_POWER mp_hal_pin_high(pyb_pin_EN_3V3); void board_early_init(void); void board_sleep(int value); From fa5c0b819c33fe81b0292570a7a1d07b6733b988 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 2 Jul 2019 14:30:43 -0700 Subject: [PATCH 0248/1299] esp32/network_ppp: Add ppp_set_usepeerdns(pcb, 1) when init'ing iface. Without this you often don't get any DNS server from your network provider. Additionally, setting your own DNS _does not work_ without this option set (which could be a bug in the PPP stack). --- ports/esp32/network_ppp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index 96d9ead305cc7..8065409158041 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -130,6 +130,7 @@ STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { mp_raise_msg(&mp_type_RuntimeError, "init failed"); } pppapi_set_default(self->pcb); + ppp_set_usepeerdns(self->pcb, 1); pppapi_connect(self->pcb, 0); xTaskCreate(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle); From 23d9c6a0fd4c125abd56fe6828084b05d6d897dd Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 5 Jul 2019 17:24:59 +1000 Subject: [PATCH 0249/1299] stm32: Add initial support for STM32L0xx MCUs. --- ports/stm32/Makefile | 16 ++++- ports/stm32/dma.c | 106 ++++++++++++++++++++++++++--- ports/stm32/dma.h | 15 ++++ ports/stm32/extint.c | 6 +- ports/stm32/flash.c | 9 ++- ports/stm32/machine_uart.c | 2 +- ports/stm32/modmachine.c | 7 +- ports/stm32/mpconfigboard_common.h | 9 +++ ports/stm32/mphalport.c | 3 + ports/stm32/powerctrl.c | 32 +++++++-- ports/stm32/rtc.c | 15 +++- ports/stm32/timer.c | 66 +++++++++++++++--- ports/stm32/uart.c | 9 ++- 13 files changed, 262 insertions(+), 33 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 3967e631170d2..3d39f0c94a37a 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -64,7 +64,7 @@ CFLAGS_CORTEX_M = -mthumb ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32F765xx STM32F767xx STM32F769xx STM32H743xx)) CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard else -ifeq ($(MCU_SERIES),f0) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0)) CFLAGS_CORTEX_M += -msoft-float else CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard @@ -75,6 +75,7 @@ endif CFLAGS_MCU_f0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0 -mcpu=cortex-m0 CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 +CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 @@ -200,7 +201,7 @@ SRC_LIBM = $(addprefix lib/libm/,\ wf_lgamma.c \ wf_tgamma.c \ ) -ifeq ($(MCU_SERIES),f0) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0)) SRC_LIBM += lib/libm/ef_sqrt.c else SRC_LIBM += lib/libm/thumb_vfp_sqrtf.c @@ -289,12 +290,21 @@ SRC_O = \ resethandler_m0.o \ lib/utils/gchelper_m0.o else +ifeq ($(MCU_SERIES),l0) +CSUPEROPT = -Os # save some code space +SRC_O = \ + $(STARTUP_FILE) \ + lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/system_stm32$(MCU_SERIES)xx.o \ + resethandler_m0.o \ + lib/utils/gchelper_m0.o +else SRC_O = \ $(STARTUP_FILE) \ system_stm32.o \ resethandler.o \ lib/utils/gchelper_m3.o endif +endif SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal.c \ @@ -341,8 +351,10 @@ endif ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c) else +ifneq ($(MCU_SERIES),$(filter $(MCU_SERIES),l0)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_can.c) endif +endif SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ core/src/usbd_core.c \ diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index a1dd40c35224a..32b9a74d709a3 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -70,7 +70,7 @@ typedef union { struct _dma_descr_t { #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) DMA_Stream_TypeDef *instance; - #elif defined(STM32F0) || defined(STM32L4) + #elif defined(STM32F0) || defined(STM32L0) || defined(STM32L4) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -310,6 +310,47 @@ static const uint8_t dma_irqn[NSTREAM] = { DMA2_Stream7_IRQn, }; +#elif defined(STM32L0) + +#define NCONTROLLERS (1) +#define NSTREAMS_PER_CONTROLLER (7) +#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER) + +#define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request) + +#define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1 + +// These descriptors are ordered by DMAx_Channel number, and within a channel by request +// number. The duplicate streams are ok as long as they aren't used at the same time. + +// DMA1 streams +const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, DMA_REQUEST_1, dma_id_1, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_3_TX = { DMA1_Channel2, DMA_REQUEST_3, dma_id_1, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, DMA_REQUEST_1, dma_id_2, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_3_RX = { DMA1_Channel3, DMA_REQUEST_3, dma_id_2, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_DAC +const dma_descr_t dma_DAC_1_TX = { DMA1_Channel3, DMA_REQUEST_6, dma_id_2, &dma_init_struct_dac }; +#endif +const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, DMA_REQUEST_1, dma_id_3, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, DMA_REQUEST_3, dma_id_3, &dma_init_struct_spi_i2c }; +#if MICROPY_HW_ENABLE_DAC +const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_5, dma_id_3, &dma_init_struct_dac }; +#endif +const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_1, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, DMA_REQUEST_3, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_3, dma_id_5, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_3, dma_id_6, &dma_init_struct_spi_i2c }; + +static const uint8_t dma_irqn[NSTREAM] = { + DMA1_Channel1_IRQn, + DMA1_Channel2_3_IRQn, + DMA1_Channel4_5_6_7_IRQn, + 0, + 0, + 0, + 0, +}; + #elif defined(STM32L4) #define NCONTROLLERS (2) @@ -459,9 +500,11 @@ volatile dma_idle_count_t dma_idle; #define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid -#if defined(STM32F0) +#if defined(STM32F0) || defined(STM32L0) #define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0) +#if defined(DMA2) #define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0) +#endif #else #define DMA1_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA1EN) != 0) #define DMA2_IS_CLK_ENABLED() ((RCC->AHB1ENR & RCC_AHB1ENR_DMA2EN) != 0) @@ -526,6 +569,44 @@ void DMA2_Stream5_IRQHandler(void) { IRQ_ENTER(DMA2_Stream5_IRQn); if (dma_handl void DMA2_Stream6_IRQHandler(void) { IRQ_ENTER(DMA2_Stream6_IRQn); if (dma_handle[dma_id_14] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_14]); } IRQ_EXIT(DMA2_Stream6_IRQn); } void DMA2_Stream7_IRQHandler(void) { IRQ_ENTER(DMA2_Stream7_IRQn); if (dma_handle[dma_id_15] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_15]); } IRQ_EXIT(DMA2_Stream7_IRQn); } +#elif defined(STM32L0) + +void DMA1_Channel1_IRQHandler(void) { + IRQ_ENTER(DMA1_Channel1_IRQn); + if (dma_handle[dma_id_0] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_0]); + } + IRQ_EXIT(DMA1_Channel1_IRQn); +} + +void DMA1_Channel2_3_IRQHandler(void) { + IRQ_ENTER(DMA1_Channel2_3_IRQn); + if (dma_handle[dma_id_1] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_1]); + } + if (dma_handle[dma_id_2] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_2]); + } + IRQ_EXIT(DMA1_Channel2_3_IRQn); +} + +void DMA1_Channel4_5_6_7_IRQHandler(void) { + IRQ_ENTER(DMA1_Channel4_5_6_7_IRQn); + if (dma_handle[dma_id_3] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_3]); + } + if (dma_handle[dma_id_4] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_4]); + } + if (dma_handle[dma_id_5] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_5]); + } + if (dma_handle[dma_id_6] != NULL) { + HAL_DMA_IRQHandler(dma_handle[dma_id_6]); + } + IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn); +} + #elif defined(STM32L4) void DMA1_Channel1_IRQHandler(void) { IRQ_ENTER(DMA1_Channel1_IRQn); if (dma_handle[dma_id_0] != NULL) { HAL_DMA_IRQHandler(dma_handle[dma_id_0]); } IRQ_EXIT(DMA1_Channel1_IRQn); } @@ -572,18 +653,21 @@ static void dma_enable_clock(dma_id_t dma_id) { dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL; } } - } else { + } + #if defined(DMA2) + else { if (((old_enable_mask & DMA2_ENABLE_MASK) == 0) && !DMA2_IS_CLK_ENABLED()) { __HAL_RCC_DMA2_CLK_ENABLE(); // We just turned on the clock. This means that anything stored - // in dma_last_channel (for DMA1) needs to be invalidated. + // in dma_last_channel (for DMA2) needs to be invalidated. for (int channel = NSTREAMS_PER_CONTROLLER; channel < NSTREAM; channel++) { dma_last_sub_instance[channel] = DMA_INVALID_CHANNEL; } } } + #endif } static void dma_disable_clock(dma_id_t dma_id) { @@ -599,7 +683,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 dma->Instance = dma_descr->instance; dma->Init = *dma_descr->init; dma->Init.Direction = dir; - #if defined(STM32L4) || defined(STM32H7) + #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) dma->Init.Request = dma_descr->sub_instance; #else #if !defined(STM32F0) @@ -705,7 +789,10 @@ static void dma_idle_handler(uint32_t tick) { } static const uint32_t controller_mask[] = { - DMA1_ENABLE_MASK, DMA2_ENABLE_MASK + DMA1_ENABLE_MASK, + #if defined(DMA2) + DMA2_ENABLE_MASK, + #endif }; { int controller = (tick >> DMA_SYSTICK_LOG2) & 1; @@ -719,9 +806,12 @@ static void dma_idle_handler(uint32_t tick) { dma_idle.counter[controller] = 0; if (controller == 0) { __HAL_RCC_DMA1_CLK_DISABLE(); - } else { + } + #if defined(DMA2) + else { __HAL_RCC_DMA2_CLK_DISABLE(); } + #endif } else { // Something is still active, but the counter never got // reset, so we'll reset the counter here. @@ -731,7 +821,7 @@ static void dma_idle_handler(uint32_t tick) { } } -#if defined(STM32F0) || defined(STM32L4) +#if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) void dma_nohal_init(const dma_descr_t *descr, uint32_t config) { DMA_Channel_TypeDef *dma = descr->instance; diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 7b74a7399349d..bedabe7f89251 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -58,6 +58,21 @@ extern const dma_descr_t dma_SPI_6_RX; extern const dma_descr_t dma_SDIO_0; extern const dma_descr_t dma_DCMI_0; +#elif defined(STM32L0) + +extern const dma_descr_t dma_SPI_1_RX; +extern const dma_descr_t dma_I2C_3_TX; +extern const dma_descr_t dma_SPI_1_TX; +extern const dma_descr_t dma_I2C_3_RX; +extern const dma_descr_t dma_DAC_1_TX; +extern const dma_descr_t dma_SPI_2_RX; +extern const dma_descr_t dma_I2C_2_TX; +extern const dma_descr_t dma_DAC_2_TX; +extern const dma_descr_t dma_SPI_2_TX; +extern const dma_descr_t dma_I2C_2_RX; +extern const dma_descr_t dma_I2C_1_TX; +extern const dma_descr_t dma_I2C_1_RX; + #elif defined(STM32L4) extern const dma_descr_t dma_ADC_1_RX; diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 0b1ba8eb09ddb..9a7295995a827 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -139,12 +139,16 @@ STATIC mp_obj_t pyb_extint_callback_arg[EXTI_NUM_VECTORS]; #endif STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32L0) EXTI0_1_IRQn, EXTI0_1_IRQn, EXTI2_3_IRQn, EXTI2_3_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, + #if defined(STM32L0) + PVD_IRQn, + #else PVD_VDDIO2_IRQn, + #endif RTC_IRQn, 0, // internal USB wakeup event RTC_IRQn, diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index 56896a7037dda..aff85f7e3798b 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -68,7 +68,7 @@ static const flash_layout_t flash_layout[] = { { 0x08040000, 0x40000, 3 }, }; -#elif defined(STM32L4) +#elif defined(STM32L0) || defined(STM32L4) static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, @@ -170,7 +170,12 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; - #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) + #elif defined(STM32L0) + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR); + EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; + EraseInitStruct.PageAddress = flash_dest; + EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; + #elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 29369c0c1411b..92343ba6d713f 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -489,7 +489,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar); // uart.sendbreak() STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - #if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) self->uartx->RQR = USART_RQR_SBKRQ; // write-only register #else self->uartx->CR1 |= USART_CR1_SBK; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index ba0ee284713bf..8d6dbf4fec49d 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -56,6 +56,11 @@ #include "uart.h" #include "wdt.h" +#if defined(STM32L0) +// L0 does not have a BOR, so use POR instead +#define RCC_CSR_BORRSTF RCC_CSR_PORRSTF +#endif + #if defined(STM32L4) // L4 does not have a POR, so use BOR instead #define RCC_CSR_PORRSTF RCC_CSR_BORRSTF @@ -300,7 +305,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } else { // set - #if defined(STM32F0) || defined(STM32L4) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) mp_raise_NotImplementedError("machine.freq set not supported yet"); #else mp_int_t sysclk = mp_obj_get_int(args[0]); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 036e1f6ccdce7..94a86ca92a4ae 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -184,6 +184,15 @@ #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) +// Configuration for STM32L0 series +#elif defined(STM32L0) + +#define MP_HAL_UNIQUE_ID_ADDRESS (0x1FF80050) +#define PYB_EXTI_NUM_VECTORS (30) // TODO (22 configurable, 7 direct) +#define MICROPY_HW_MAX_I2C (3) +#define MICROPY_HW_MAX_TIMER (22) +#define MICROPY_HW_MAX_UART (4) + // Configuration for STM32L4 series #elif defined(STM32L4) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 79b28bd3defcc..c5786e7409314 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -119,6 +119,9 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #elif defined(STM32H7) #define AHBxENR AHB4ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB4ENR_GPIOAEN_Pos + #elif defined(STM32L0) + #define AHBxENR IOPENR + #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_GPIOAEN #elif defined(STM32L4) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index e3ad20039c2d8..cf2445c7d9ad9 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -84,7 +84,31 @@ void powerctrl_check_enter_bootloader(void) { } } -#if !defined(STM32F0) +#if defined(STM32L0) +void SystemClock_Config(void) { + // Enable power control peripheral + __HAL_RCC_PWR_CLK_ENABLE(); + + // Use the 16MHz internal oscillator + RCC->CR |= RCC_CR_HSION; + while (!(RCC->CR & RCC_CR_HSIRDY)) { + } + const uint32_t sysclk_src = 1; + + // Select SYSCLK source + RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { + // Wait for SYSCLK source to change + } + + SystemCoreClockUpdate(); + + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); +} +#endif + +#if !defined(STM32F0) && !defined(STM32L0) // Assumes that PLL is used as the SYSCLK source int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) { @@ -158,7 +182,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk #endif -#if !(defined(STM32F0) || defined(STM32L4)) +#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; } @@ -333,7 +357,7 @@ void powerctrl_enter_stop_mode(void) { __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif - #if !defined(STM32F0) && !defined(STM32L4) + #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif @@ -426,7 +450,7 @@ void powerctrl_enter_standby_mode(void) { // Note: we only support RTC ALRA, ALRB, WUT and TS. // TODO support TAMP and WKUP (PA0 external pin). - #if defined(STM32F0) + #if defined(STM32F0) || defined(STM32L0) #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_WUTIE | RTC_CR_TSIE) #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TSF) #else diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index a7c3f2068b8d8..d0f444c216269 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -73,6 +73,17 @@ STATIC bool rtc_use_lse = false; STATIC uint32_t rtc_startup_tick; STATIC bool rtc_need_init_finalise = false; +#if defined(STM32L0) +#define BDCR CSR +#define RCC_BDCR_RTCEN RCC_CSR_RTCEN +#define RCC_BDCR_RTCSEL RCC_CSR_RTCSEL +#define RCC_BDCR_RTCSEL_0 RCC_CSR_RTCSEL_0 +#define RCC_BDCR_RTCSEL_1 RCC_CSR_RTCSEL_1 +#define RCC_BDCR_LSEON RCC_CSR_LSEON +#define RCC_BDCR_LSERDY RCC_CSR_LSERDY +#define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP +#endif + void rtc_init_start(bool force_init) { RTCHandle.Instance = RTC; @@ -287,7 +298,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) { // Exit Initialization mode hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; - #if defined(STM32L4) || defined(STM32H7) + #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMOUTTYPE; hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType); #elif defined(STM32F7) @@ -539,7 +550,7 @@ mp_obj_t pyb_rtc_datetime(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime); -#if defined(STM32F0) +#if defined(STM32F0) || defined(STM32L0) #define RTC_WKUP_IRQn RTC_IRQn #endif diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 7f4c0d85a9547..cd01a41741e3f 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -427,6 +427,8 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) { #endif } +#if !defined(STM32L0) + // Computes the 8-bit value for the DTG field in the BDTR register. // // 1 tick = 1 count of the timer's clock (source_freq) divided by div. @@ -486,6 +488,8 @@ STATIC void config_deadtime(pyb_timer_obj_t *self, mp_int_t ticks, mp_int_t brk) HAL_TIMEx_ConfigBreakDeadTime(&self->tim, &deadTimeConfig); } +#endif + TIM_HandleTypeDef *pyb_timer_get_handle(mp_obj_t timer) { if (mp_obj_get_type(timer) != &pyb_timer_type) { mp_raise_ValueError("need a Timer object"); @@ -514,6 +518,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 : self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1); + #if !defined(STM32L0) #if defined(IS_TIM_ADVANCED_INSTANCE) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) #elif defined(IS_TIM_BREAK_INSTANCE) @@ -531,6 +536,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ mp_printf(print, ", brk=BRK_OFF"); } } + #endif mp_print_str(print, ")"); } } @@ -630,11 +636,15 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons args[ARG_div].u_int == 4 ? TIM_CLOCKDIVISION_DIV4 : TIM_CLOCKDIVISION_DIV1; + #if !defined(STM32L0) init->RepetitionCounter = 0; + #endif // enable TIM clock switch (self->tim_id) { + #if defined(TIM1) case 1: __HAL_RCC_TIM1_CLK_ENABLE(); break; + #endif case 2: __HAL_RCC_TIM2_CLK_ENABLE(); break; #if defined(TIM3) case 3: __HAL_RCC_TIM3_CLK_ENABLE(); break; @@ -681,22 +691,40 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons #if defined(TIM17) case 17: __HAL_RCC_TIM17_CLK_ENABLE(); break; #endif + #if defined(TIM18) + case 18: __HAL_RCC_TIM18_CLK_ENABLE(); break; + #endif + #if defined(TIM19) + case 19: __HAL_RCC_TIM19_CLK_ENABLE(); break; + #endif + #if defined(TIM20) + case 20: __HAL_RCC_TIM20_CLK_ENABLE(); break; + #endif + #if defined(TIM21) + case 21: __HAL_RCC_TIM21_CLK_ENABLE(); break; + #endif + #if defined(TIM22) + case 22: __HAL_RCC_TIM22_CLK_ENABLE(); break; + #endif } // set IRQ priority (if not a special timer) if (self->tim_id != 5) { NVIC_SetPriority(IRQn_NONNEG(self->irqn), IRQ_PRI_TIMX); if (self->tim_id == 1) { + #if defined(TIM1) NVIC_SetPriority(TIM1_CC_IRQn, IRQ_PRI_TIMX); - #if defined(TIM8) + #endif } else if (self->tim_id == 8) { + #if defined(TIM8) NVIC_SetPriority(TIM8_CC_IRQn, IRQ_PRI_TIMX); - #endif + #endif } } // init TIM HAL_TIM_Base_Init(&self->tim); + #if !defined(STM32L0) #if defined(IS_TIM_ADVANCED_INSTANCE) if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance)) { #elif defined(IS_TIM_BREAK_INSTANCE) @@ -707,6 +735,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons config_deadtime(self, args[ARG_deadtime].u_int, args[ARG_brk].u_int); } + #endif // Enable ARPE so that the auto-reload register is buffered. // This allows to smoothly change the frequency of the timer. @@ -726,6 +755,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons // It assumes that timer instance pointer has the lower 8 bits cleared. #define TIM_ENTRY(id, irq) [id - 1] = (uint32_t)TIM##id | irq STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { + #if defined(TIM1) #if defined(STM32F0) TIM_ENTRY(1, TIM1_BRK_UP_TRG_COM_IRQn), #elif defined(STM32F4) || defined(STM32F7) @@ -733,6 +763,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #elif defined(STM32L4) TIM_ENTRY(1, TIM1_UP_TIM16_IRQn), #endif + #endif TIM_ENTRY(2, TIM2_IRQn), #if defined(TIM3) TIM_ENTRY(3, TIM3_IRQn), @@ -1054,10 +1085,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma oc_config.Pulse = args[3].u_int; } oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; - oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; oc_config.OCFastMode = TIM_OCFAST_DISABLE; + #if !defined(STM32L0) + oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; oc_config.OCIdleState = TIM_OCIDLESTATE_SET; oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; + #endif HAL_TIM_PWM_ConfigChannel(&self->tim, &oc_config, TIMER_CHANNEL(chan)); if (chan->callback == mp_const_none) { @@ -1065,10 +1098,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma } else { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); } + #if !defined(STM32L0) // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { HAL_TIMEx_PWMN_Start(&self->tim, TIMER_CHANNEL(chan)); } + #endif break; } @@ -1085,14 +1120,16 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma if (oc_config.OCPolarity == 0xffffffff) { oc_config.OCPolarity = TIM_OCPOLARITY_HIGH; } + oc_config.OCFastMode = TIM_OCFAST_DISABLE; + #if !defined(STM32L0) if (oc_config.OCPolarity == TIM_OCPOLARITY_HIGH) { oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH; } else { oc_config.OCNPolarity = TIM_OCNPOLARITY_LOW; } - oc_config.OCFastMode = TIM_OCFAST_DISABLE; oc_config.OCIdleState = TIM_OCIDLESTATE_SET; oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET; + #endif if (!IS_TIM_OC_POLARITY(oc_config.OCPolarity)) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", oc_config.OCPolarity)); @@ -1103,10 +1140,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma } else { pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback); } + #if !defined(STM32L0) // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { HAL_TIMEx_OCN_Start(&self->tim, TIMER_CHANNEL(chan)); } + #endif break; } @@ -1155,8 +1194,12 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid polarity (%d)", enc_config.IC1Polarity)); } // Only Timers 1, 2, 3, 4, 5, and 8 support encoder mode - if (self->tim.Instance != TIM1 - && self->tim.Instance != TIM2 + if ( + #if defined(TIM1) + self->tim.Instance != TIM1 + && + #endif + self->tim.Instance != TIM2 #if defined(TIM3) && self->tim.Instance != TIM3 #endif @@ -1426,15 +1469,18 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback) self->callback = mp_const_none; } else if (mp_obj_is_callable(callback)) { self->callback = callback; - uint8_t tim_id = self->timer->tim_id; __HAL_TIM_CLEAR_IT(&self->timer->tim, TIMER_IRQ_MASK(self->channel)); - if (tim_id == 1) { + #if defined(TIM1) + if (self->timer->tim_id == 1) { HAL_NVIC_EnableIRQ(TIM1_CC_IRQn); + } else + #endif #if defined(TIM8) // STM32F401 doesn't have a TIM8 - } else if (tim_id == 8) { + if (self->timer->tim_id == 8) { HAL_NVIC_EnableIRQ(TIM8_CC_IRQn); + } else #endif - } else { + { HAL_NVIC_EnableIRQ(self->timer->irqn); } // start timer, so that it interrupts on overflow diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 3a21a0b31ebe4..0d46ea9473599 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -76,6 +76,11 @@ #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_RXFTIE | USART_CR3_TCBGTIE | USART_CR3_TXFTIE | USART_CR3_WUFIE) +#elif defined(STM32L0) +#define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) +#define USART_CR2_IE_ALL (USART_CR2_IE_BASE) +#define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) + #elif defined(STM32L4) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) @@ -648,7 +653,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) int data = self->uartx->RDR & self->char_mask; self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set return data; @@ -774,7 +779,7 @@ void uart_irq_handler(mp_uint_t uart_id) { uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len; if (next_head != self->read_buf_tail) { // only read data if room in buf - #if defined(STM32F0) || defined(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) int data = self->uartx->RDR; // clears UART_FLAG_RXNE self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set #else From 9c096c190c68e527d617d596037f6f0d497da85a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 5 Jul 2019 17:26:03 +1000 Subject: [PATCH 0250/1299] stm32/boards: Add MCU support files for STM32L072. --- ports/stm32/boards/stm32l072_af.csv | 84 ++++++++++++++++++ ports/stm32/boards/stm32l072xz.ld | 27 ++++++ ports/stm32/boards/stm32l0xx_hal_conf_base.h | 91 ++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 ports/stm32/boards/stm32l072_af.csv create mode 100644 ports/stm32/boards/stm32l072xz.ld create mode 100644 ports/stm32/boards/stm32l0xx_hal_conf_base.h diff --git a/ports/stm32/boards/stm32l072_af.csv b/ports/stm32/boards/stm32l072_af.csv new file mode 100644 index 0000000000000..0b1115b164a90 --- /dev/null +++ b/ports/stm32/boards/stm32l072_af.csv @@ -0,0 +1,84 @@ +Port,Pin,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,, +,,SPI1/SPI2/I2S2/USART1/2/LPUART1/USB/LPTIM1/TSC/TIM2/21/22/EVENTOUT/SYS_AF,SPI1/SPI2/I2S2/I2C1/TIM2/21,SPI1/SPI2/I2S2/LPUART1/USART5/USB/LPTIM1/TIM2/3/EVENTOUT/SYS_AF,I2C1/TSC/EVENTOUT,I2C1/USART1/2/LPUART1/TIM3/22/EVENTOUT,SPI2/I2S2/I2C2/USART1/TIM2/21/22,I2C1/2/LPUART1/USART4/UASRT5/TIM21/EVENTOUT,I2C3/LPUART1/COMP1/2/TIM3,,ADC +PortA,PA0,,,TIM2_CH1,TSC_G1_IO1,USART2_CTS,TIM2_ETR,USART4_TX,COMP1_OUT,,ADC_IN0 +PortA,PA1,EVENTOUT,,TIM2_CH2,TSC_G1_IO2,USART2_RTS_DE,TIM21_ETR,USART4_RX,,,ADC_IN1 +PortA,PA2,TIM21_CH1,,TIM2_CH3,TSC_G1_IO3,USART2_TX,,LPUART1_TX,COMP2_OUT,,ADC_IN2 +PortA,PA3,TIM21_CH2,,TIM2_CH4,TSC_G1_IO4,USART2_RX,,LPUART1_RX,,,ADC_IN3 +PortA,PA4,SPI1_NSS,,,TSC_G2_IO1,USART2_CK,TIM22_ETR,,,,ADC_IN4 +PortA,PA5,SPI1_SCK,,TIM2_ETR,TSC_G2_IO2,,TIM2_CH1,,,,ADC_IN5 +PortA,PA6,SPI1_MISO,,TIM3_CH1,TSC_G2_IO3,LPUART1_CTS,TIM22_CH1,EVENTOUT,COMP1_OUT,,ADC_IN6 +PortA,PA7,SPI1_MOSI,,TIM3_CH2,TSC_G2_IO4,,TIM22_CH2,EVENTOUT,COMP2_OUT,,ADC_IN7 +PortA,PA8,MCO,,USB_CRS_SYNC,EVENTOUT,USART1_CK,,,I2C3_SCL,, +PortA,PA9,MCO,,,TSC_G4_IO1,USART1_TX,,I2C1_SCL,I2C3_SMBA,, +PortA,PA10,,,,TSC_G4_IO2,USART1_RX,,I2C1_SDA,,, +PortA,PA11,SPI1_MISO,,EVENTOUT,TSC_G4_IO3,USART1_CTS,,,COMP1_OUT,, +PortA,PA12,SPI1_MOSI,,EVENTOUT,TSC_G4_IO4,USART1_RTS_DE,,,COMP2_OUT,, +PortA,PA13,SWDIO,,USB_NOE,,,,LPUART1_RX,,, +PortA,PA14,SWCLK,,,,USART2_TX,,LPUART1_TX,,, +PortA,PA15,SPI1_NSS,,TIM2_ETR,EVENTOUT,USART2_RX,TIM2_CH1,USART4_RTS_DE,,, +PortB,PB0,EVENTOUT,,TIM3_CH3,TSC_G3_IO2,,,,,,ADC_IN8 +PortB,PB1,,,TIM3_CH4,TSC_G3_IO3,LPUART1_RTS_DE,,,,,ADC_IN9 +PortB,PB2,,,LPTIM1_OUT,TSC_G3_IO4,,,,I2C3_SMBA,, +PortB,PB3,SPI1_SCK,,TIM2_CH2,TSC_G5_IO1,EVENTOUT,USART1_RTS_DE,USART5_TX,,, +PortB,PB4,SPI1_MISO,,TIM3_CH1,TSC_G5_IO2,TIM22_CH1,USART1_CTS,USART5_RX,I2C3_SDA,, +PortB,PB5,SPI1_MOSI,,LPTIM1_IN1,I2C1_SMBA,TIM3_CH2/TIM22_CH2,USART1_CK,USART5_CK/USART5_RTS_DE,,, +PortB,PB6,USART1_TX,I2C1_SCL,LPTIM1_ETR,TSC_G5_IO3,,,,,, +PortB,PB7,USART1_RX,I2C1_SDA,LPTIM1_IN2,TSC_G5_IO4,,,USART4_CTS,,, +PortB,PB8,,,,TSC_SYNC,I2C1_SCL,,,,, +PortB,PB9,,,EVENTOUT,,I2C1_SDA,SPI2_NSS/I2S2_WS,,,, +PortB,PB10,,,TIM2_CH3,TSC_SYNC,LPUART1_TX,SPI2_SCK,I2C2_SCL,LPUART1_RX,, +PortB,PB11,EVENTOUT,,TIM2_CH4,TSC_G6_IO1,LPUART1_RX,,I2C2_SDA,LPUART1_TX,, +PortB,PB12,SPI2_NSS/I2S2_WS,,LPUART1_RTS_DE,TSC_G6_IO2,I2C2_SMBA,,EVENTOUT,,, +PortB,PB13,SPI2_SCK/I2S2_CK,,MCO,TSC_G6_IO3,LPUART1_CTS,I2C2_SCL,TIM21_CH1,,, +PortB,PB14,SPI2_MISO/I2S2_MCK,,RTC_OUT,TSC_G6_IO4,LPUART1_RTS_DE,I2C2_SDA,TIM21_CH2,,, +PortB,PB15,SPI2_MOSI/I2S2_SD,,RTC_REFIN,,,,,,, +PortC,PC0,LPTIM1_IN1,,EVENTOUT,TSC_G7_IO1,,,LPUART1_RX,I2C3_SCL,,ADC_IN10 +PortC,PC1,LPTIM1_OUT,,EVENTOUT,TSC_G7_IO2,,,LPUART1_TX,I2C3_SDA,,ADC_IN11 +PortC,PC2,LPTIM1_IN2,,SPI2_MISO/I2S2_MCK,TSC_G7_IO3,,,,,,ADC_IN12 +PortC,PC3,LPTIM1_ETR,,SPI2_MOSI/I2S2_SD,TSC_G7_IO4,,,,,,ADC_IN13 +PortC,PC4,EVENTOUT,,LPUART1_TX,,,,,,,ADC_IN14 +PortC,PC5,LPUART1_RX,,TSC_G3_IO1,,,,,,,ADC_IN15 +PortC,PC6,TIM22_CH1,,TIM3_CH1,TSC_G8_IO1,,,,,, +PortC,PC7,TIM22_CH2,,TIM3_CH2,TSC_G8_IO2,,,,,, +PortC,PC8,TIM22_ETR,,TIM3_CH3,TSC_G8_IO3,,,,,, +PortC,PC9,TIM21_ETR,,USB_NOE/TIM3_CH4,TSC_G8_IO4,,,,I2C3_SDA,, +PortC,PC10,LPUART1_TX,,,,,,USART4_TX,,, +PortC,PC11,LPUART1_RX,,,,,,USART4_RX,,, +PortC,PC12,,,USART5_TX,,,,USART4_CK,,, +PortC,PC13,,,,,,,,,, +PortC,PC14,,,,,,,,,, +PortC,PC15,,,,,,,,,, +PortD,PD0,TIM21_CH1,SPI2_NSS/I2S2_WS,,,,,,,, +PortD,PD1,,SPI2_SCK/I2S2_CK,,,,,,,, +PortD,PD2,LPUART1_RTS_DE,,TIM3_ETR,,,,USART5_RX,,, +PortD,PD3,USART2_CTS,,SPI2_MISO/I2S2_MCK,,,,,,, +PortD,PD4,USART2_RTS_DE,SPI2_MOSI/I2S2_SD,,,,,,,, +PortD,PD5,USART2_TX,,,,,,,,, +PortD,PD6,USART2_RX,,,,,,,,, +PortD,PD7,USART2_CK,TIM21_CH2,,,,,,,, +PortD,PD8,LPUART1_TX,,,,,,,,, +PortD,PD9,LPUART1_RX,,,,,,,,, +PortD,PD10,,,,,,,,,, +PortD,PD11,LPUART1_CTS,,,,,,,,, +PortD,PD12,LPUART1_RTS_DE,,,,,,,,, +PortD,PD13,,,,,,,,,, +PortD,PD14,,,,,,,,,, +PortD,PD15,USB_CRS_SYNC,,,,,,,,, +PortE,PE0,,,EVENTOUT,,,,,,, +PortE,PE1,,,EVENTOUT,,,,,,, +PortE,PE2,,,TIM3_ETR,,,,,,, +PortE,PE3,TIM22_CH1,,TIM3_CH1,,,,,,, +PortE,PE4,TIM22_CH2,,TIM3_CH2,,,,,,, +PortE,PE5,TIM21_CH1,,TIM3_CH3,,,,,,, +PortE,PE6,TIM21_CH2,,TIM3_CH4,,,,,,, +PortE,PE7,,,,,,,USART5_CK/USART5_RTS_DE,,, +PortE,PE8,,,,,,,USART4_TX,,, +PortE,PE9,TIM2_CH1,,TIM2_ETR,,,,USART4_RX,,, +PortE,PE10,TIM2_CH2,,,,,,USART5_TX,,, +PortE,PE11,TIM2_CH3,,,,,,USART5_RX,,, +PortE,PE12,TIM2_CH4,,SPI1_NSS,,,,,,, +PortE,PE13,,,SPI1_SCK,,,,,,, +PortE,PE14,,,SPI1_MISO,,,,,,, +PortE,PE15,,,SPI1_MOSI,,,,,,, +PortH,PH0,USB_CRS_SYNC,,,,,,,,, +PortH,PH1,,,,,,,,,, diff --git a/ports/stm32/boards/stm32l072xz.ld b/ports/stm32/boards/stm32l072xz.ld new file mode 100644 index 0000000000000..538950747be00 --- /dev/null +++ b/ports/stm32/boards/stm32l072xz.ld @@ -0,0 +1,27 @@ +/* + GNU linker script for STM32F072xZ +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 192K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 8K; + +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); + +/* Define the top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve; +_sstack = _estack - 4K; + +/* RAM extents for the main heap */ +_heap_start = _ebss; +_heap_end = _sstack; diff --git a/ports/stm32/boards/stm32l0xx_hal_conf_base.h b/ports/stm32/boards/stm32l0xx_hal_conf_base.h new file mode 100644 index 0000000000000..ed524fecca9c3 --- /dev/null +++ b/ports/stm32/boards/stm32l0xx_hal_conf_base.h @@ -0,0 +1,91 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32L0XX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32L0XX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32l0xx_hal_dma.h" +#include "stm32l0xx_hal_adc.h" +#include "stm32l0xx_hal_cortex.h" +#include "stm32l0xx_hal_crc.h" +#include "stm32l0xx_hal_dac.h" +#include "stm32l0xx_hal_flash.h" +#include "stm32l0xx_hal_gpio.h" +#include "stm32l0xx_hal_i2c.h" +#include "stm32l0xx_hal_i2s.h" +#include "stm32l0xx_hal_iwdg.h" +#include "stm32l0xx_hal_pcd.h" +#include "stm32l0xx_hal_pwr.h" +#include "stm32l0xx_hal_rcc.h" +#include "stm32l0xx_hal_rtc.h" +#include "stm32l0xx_hal_spi.h" +#include "stm32l0xx_hal_tim.h" +#include "stm32l0xx_hal_uart.h" +#include "stm32l0xx_hal_usart.h" +#include "stm32l0xx_hal_wwdg.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +// Oscillator values in Hz +#define HSI_VALUE (16000000) +#define HSI48_VALUE (48000000) +#define LSI_VALUE (37000) +#define MSI_VALUE (2097152) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define PREFETCH_ENABLE 1 +#define PREREAD_ENABLE 0 +#define BUFFER_CACHE_DISABLE 0 +#define USE_RTOS 0 +#define USE_SPI_CRC 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32L0XX_HAL_CONF_BASE_H From 6053e450b8e3600b96a3e99174ea3385cec9c2dd Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 5 Jul 2019 17:26:49 +1000 Subject: [PATCH 0251/1299] stm32/mpconfigport.h: Make "framebuf" module configurable by a board. --- ports/stm32/mpconfigport.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 5095dde52b8d8..3e615c343731b 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -165,7 +165,9 @@ #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (HAL_RCC_GetSysClockFreq() / 48) #define MICROPY_PY_UWEBSOCKET (MICROPY_PY_LWIP) #define MICROPY_PY_WEBREPL (MICROPY_PY_LWIP) +#ifndef MICROPY_PY_FRAMEBUF #define MICROPY_PY_FRAMEBUF (1) +#endif #ifndef MICROPY_PY_USOCKET #define MICROPY_PY_USOCKET (1) #endif From 7c2e83324b1abfbec2bfaee2c60b50ceb3f9185a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 5 Jul 2019 17:28:54 +1000 Subject: [PATCH 0252/1299] stm32/boards/NUCLEO_L073RZ: Add definition files for new board. --- .../boards/NUCLEO_L073RZ/mpconfigboard.h | 53 +++++++++++ .../boards/NUCLEO_L073RZ/mpconfigboard.mk | 7 ++ ports/stm32/boards/NUCLEO_L073RZ/pins.csv | 87 +++++++++++++++++++ .../boards/NUCLEO_L073RZ/stm32l0xx_hal_conf.h | 18 ++++ 4 files changed, 165 insertions(+) create mode 100644 ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h create mode 100644 ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk create mode 100644 ports/stm32/boards/NUCLEO_L073RZ/pins.csv create mode 100644 ports/stm32/boards/NUCLEO_L073RZ/stm32l0xx_hal_conf.h diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h new file mode 100644 index 0000000000000..ff4be4a27707e --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h @@ -0,0 +1,53 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * MIT License; Copyright (c) 2019 Damien P. George + */ + +#define MICROPY_HW_BOARD_NAME "NUCLEO-L073RZ" +#define MICROPY_HW_MCU_NAME "STM32F073RZT6" + +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_PY_BUILTINS_COMPLEX (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_FRAMEBUF (0) +#define MICROPY_PY_USOCKET (0) +#define MICROPY_PY_NETWORK (0) +#define MICROPY_PY_STM (0) +#define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_VFS_FAT (0) + +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_ADC (0) +#define MICROPY_HW_HAS_SWITCH (1) + +// UART config +#define MICROPY_HW_UART1_TX (pin_B6) +#define MICROPY_HW_UART1_RX (pin_B7) +#define MICROPY_HW_UART2_TX (pin_A2) +#define MICROPY_HW_UART2_RX (pin_A3) + +// USART2 is connected to the ST-LINK USB VCP +#define MICROPY_HW_UART_REPL PYB_UART_2 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C busses +#define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 +#define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino D14, pin 5 on CN10 + +// SPI busses +#define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 +#define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 +#define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 +#define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 + +// USER B1 has a pull-up and is active low +#define MICROPY_HW_USRSW_PIN (pin_C13) +#define MICROPY_HW_USRSW_PULL (0) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// NUCLEO-64 has one user LED +#define MICROPY_HW_LED1 (pin_A5) // green +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk new file mode 100644 index 0000000000000..69601f8602800 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk @@ -0,0 +1,7 @@ +MCU_SERIES = l0 +CMSIS_MCU = STM32L073xx +AF_FILE = boards/stm32l072_af.csv +LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld + +# Don't include default frozen modules because MCU is tight on flash space +FROZEN_MPY_DIR ?= diff --git a/ports/stm32/boards/NUCLEO_L073RZ/pins.csv b/ports/stm32/boards/NUCLEO_L073RZ/pins.csv new file mode 100644 index 0000000000000..36d314108364f --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L073RZ/pins.csv @@ -0,0 +1,87 @@ +D0,PA3 +D1,PA2 +D2,PA10 +D3,PB3 +D4,PB5 +D5,PB4 +D6,PB10 +D7,PA8 +D8,PA9 +D9,PC7 +D10,PB6 +D11,PA7 +D12,PA6 +D13,PA5 +D14,PB9 +D15,PB8 +A0,PA0 +A1,PA1 +A2,PA4 +A3,PB0 +A4,PC1 +A5,PC0 +RX,PA3 +TX,PA2 +SCL,PB8 +SDA,PB9 +SCK,PA5 +MISO,PA6 +MOSI,PA7 +CS,PB6 +BOOT0,PF11 +SWDIO,PA13 +SWCLK,PA14 +USER_B1,PC13 +LED_GREEN,PA5 +PA0,PA0 +PA1,PA1 +PA2,PA2 +PA3,PA3 +PA4,PA4 +PA5,PA5 +PA6,PA6 +PA7,PA7 +PA8,PA8 +PA9,PA9 +PA10,PA10 +PA11,PA11 +PA12,PA12 +PA13,PA13 +PA14,PA14 +PA15,PA15 +PB0,PB0 +PB1,PB1 +PB2,PB2 +PB3,PB3 +PB4,PB4 +PB5,PB5 +PB6,PB6 +PB7,PB7 +PB8,PB8 +PB9,PB9 +PB10,PB10 +PB11,PB11 +PB12,PB12 +PB13,PB13 +PB14,PB14 +PB15,PB15 +PC0,PC0 +PC1,PC1 +PC2,PC2 +PC3,PC3 +PC4,PC4 +PC5,PC5 +PC6,PC6 +PC7,PC7 +PC8,PC8 +PC9,PC9 +PC10,PC10 +PC11,PC11 +PC12,PC12 +PC13,PC13 +PC14,PC14 +PC15,PC15 +PD2,PD2 +PF0,PF0 +PF1,PF1 +PF11,PF11 diff --git a/ports/stm32/boards/NUCLEO_L073RZ/stm32l0xx_hal_conf.h b/ports/stm32/boards/NUCLEO_L073RZ/stm32l0xx_hal_conf.h new file mode 100644 index 0000000000000..c88a7065103d3 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L073RZ/stm32l0xx_hal_conf.h @@ -0,0 +1,18 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H + +#include "boards/stm32l0xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H From 21ecf8be5fd13510299acfad557f5d129bed3706 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 8 Jul 2019 15:07:39 +1000 Subject: [PATCH 0253/1299] stm32/powerctrl: Move L0's SystemClock_Config to powerctrlboot.c file. --- ports/stm32/Makefile | 1 + ports/stm32/main.c | 2 -- ports/stm32/powerctrl.c | 24 ----------------- ports/stm32/powerctrl.h | 2 ++ ports/stm32/powerctrlboot.c | 54 +++++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 26 deletions(-) create mode 100644 ports/stm32/powerctrlboot.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 3d39f0c94a37a..cddebbf5422a1 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -233,6 +233,7 @@ SRC_C = \ pendsv.c \ systick.c \ powerctrl.c \ + powerctrlboot.c \ pybthread.c \ factoryreset.c \ timer.c \ diff --git a/ports/stm32/main.c b/ports/stm32/main.c index e470522fbd515..cd4aaa4845023 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -71,8 +71,6 @@ #include "can.h" #include "modnetwork.h" -void SystemClock_Config(void); - #if MICROPY_PY_THREAD STATIC pyb_thread_t pyb_thread_main; #endif diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index cf2445c7d9ad9..067e4c176e518 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -84,30 +84,6 @@ void powerctrl_check_enter_bootloader(void) { } } -#if defined(STM32L0) -void SystemClock_Config(void) { - // Enable power control peripheral - __HAL_RCC_PWR_CLK_ENABLE(); - - // Use the 16MHz internal oscillator - RCC->CR |= RCC_CR_HSION; - while (!(RCC->CR & RCC_CR_HSIRDY)) { - } - const uint32_t sysclk_src = 1; - - // Select SYSCLK source - RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; - while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { - // Wait for SYSCLK source to change - } - - SystemCoreClockUpdate(); - - HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); -} -#endif - #if !defined(STM32F0) && !defined(STM32L0) // Assumes that PLL is used as the SYSCLK source diff --git a/ports/stm32/powerctrl.h b/ports/stm32/powerctrl.h index 6eb0342287c62..6e5f899a4cd1b 100644 --- a/ports/stm32/powerctrl.h +++ b/ports/stm32/powerctrl.h @@ -28,6 +28,8 @@ #include +void SystemClock_Config(void); + NORETURN void powerctrl_mcu_reset(void); NORETURN void powerctrl_enter_bootloader(uint32_t r0, uint32_t bl_addr); void powerctrl_check_enter_bootloader(void); diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c new file mode 100644 index 0000000000000..66beff27c64e9 --- /dev/null +++ b/ports/stm32/powerctrlboot.c @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mphal.h" +#include "powerctrl.h" + +#if defined(STM32L0) + +void SystemClock_Config(void) { + // Enable power control peripheral + __HAL_RCC_PWR_CLK_ENABLE(); + + // Use the 16MHz internal oscillator + RCC->CR |= RCC_CR_HSION; + while (!(RCC->CR & RCC_CR_HSIRDY)) { + } + const uint32_t sysclk_src = 1; + + // Select SYSCLK source + RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { + // Wait for SYSCLK source to change + } + + SystemCoreClockUpdate(); + + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); +} + +#endif From c15dc2c4b964811c150ccf164edb86a06ed6cd51 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 8 Jul 2019 15:13:54 +1000 Subject: [PATCH 0254/1299] stm32/powerctrl: Move F0's SystemClock_Config to powerctrlboot.c. --- ports/stm32/powerctrlboot.c | 51 +++++++++++++++++++++++++++++++++++- ports/stm32/system_stm32f0.c | 47 --------------------------------- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 66beff27c64e9..527118ba88f1a 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -27,7 +27,56 @@ #include "py/mphal.h" #include "powerctrl.h" -#if defined(STM32L0) +#if defined(STM32F0) + +void SystemClock_Config(void) { + // Enable power control peripheral + __HAL_RCC_PWR_CLK_ENABLE(); + + // Set flash latency to 1 because SYSCLK > 24MHz + FLASH->ACR = (FLASH->ACR & ~0x7) | 0x1; + + #if MICROPY_HW_CLK_USE_HSI48 + // Use the 48MHz internal oscillator + + RCC->CR2 |= RCC_CR2_HSI48ON; + while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) { + } + const uint32_t sysclk_src = 3; + + #else + // Use HSE and the PLL to get a 48MHz SYSCLK + + #if MICROPY_HW_CLK_USE_BYPASS + RCC->CR |= RCC_CR_HSEBYP; + #endif + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0) { + // Wait for HSE to be ready + } + RCC->CFGR = ((48000000 / HSE_VALUE) - 2) << RCC_CFGR_PLLMUL_Pos | 2 << RCC_CFGR_PLLSRC_Pos; + RCC->CFGR2 = 0; // Input clock not divided + RCC->CR |= RCC_CR_PLLON; // Turn PLL on + while ((RCC->CR & RCC_CR_PLLRDY) == 0) { + // Wait for PLL to lock + } + const uint32_t sysclk_src = 2; + + #endif + + // Select SYSCLK source + RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { + // Wait for SYSCLK source to change + } + + SystemCoreClockUpdate(); + + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); +} + +#elif defined(STM32L0) void SystemClock_Config(void) { // Enable power control peripheral diff --git a/ports/stm32/system_stm32f0.c b/ports/stm32/system_stm32f0.c index c3c675c7459a7..4f561145ccabb 100644 --- a/ports/stm32/system_stm32f0.c +++ b/ports/stm32/system_stm32f0.c @@ -128,53 +128,6 @@ void SystemInit(void) { SCB->CCR |= SCB_CCR_STKALIGN_Msk; } -void SystemClock_Config(void) { - // Enable power control peripheral - __HAL_RCC_PWR_CLK_ENABLE(); - - // Set flash latency to 1 because SYSCLK > 24MHz - FLASH->ACR = (FLASH->ACR & ~0x7) | 0x1; - - #if MICROPY_HW_CLK_USE_HSI48 - // Use the 48MHz internal oscillator - - RCC->CR2 |= RCC_CR2_HSI48ON; - while ((RCC->CR2 & RCC_CR2_HSI48RDY) == 0) { - } - const uint32_t sysclk_src = 3; - - #else - // Use HSE and the PLL to get a 48MHz SYSCLK - - #if MICROPY_HW_CLK_USE_BYPASS - RCC->CR |= RCC_CR_HSEBYP; - #endif - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0) { - // Wait for HSE to be ready - } - RCC->CFGR = ((48000000 / HSE_VALUE) - 2) << RCC_CFGR_PLLMUL_Pos | 2 << RCC_CFGR_PLLSRC_Pos; - RCC->CFGR2 = 0; // Input clock not divided - RCC->CR |= RCC_CR_PLLON; // Turn PLL on - while ((RCC->CR & RCC_CR_PLLRDY) == 0) { - // Wait for PLL to lock - } - const uint32_t sysclk_src = 2; - - #endif - - // Select SYSCLK source - RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; - while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { - // Wait for SYSCLK source to change - } - - SystemCoreClockUpdate(); - - HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); -} - void SystemCoreClockUpdate(void) { // Get SYSCLK source uint32_t tmp = RCC->CFGR & RCC_CFGR_SWS; From 5fd62c899226fbaac96a758e9f2b4fef5afcf19b Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 8 Jul 2019 15:16:26 +1000 Subject: [PATCH 0255/1299] stm32: Remove SystemInit funcs, use stm32lib versions instead. stm32lib now provides system_stm32XXxx.c source files for all MCU variants, which includes SystemInit and prescaler tables. Since these are quite standard and don't need to be changed, switch to use them instead of custom variants, making the start-up code cleaner. The SystemInit code in stm32lib was checked and is equivalent to what is removed from the stm32 port in this commit. --- ports/stm32/Makefile | 14 +-- ports/stm32/main.c | 8 ++ ports/stm32/system_stm32.c | 211 ----------------------------------- ports/stm32/system_stm32f0.c | 184 ------------------------------ 4 files changed, 15 insertions(+), 402 deletions(-) delete mode 100644 ports/stm32/system_stm32f0.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index cddebbf5422a1..84ce01e8f951a 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -43,6 +43,7 @@ STFLASH ?= st-flash OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o +SYSTEM_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/system_stm32$(MCU_SERIES)xx.o # Select the cross compile prefix CROSS_COMPILE ?= arm-none-eabi- @@ -284,23 +285,22 @@ SRC_C = \ adc.c \ $(wildcard $(BOARD_DIR)/*.c) -ifeq ($(MCU_SERIES),f0) SRC_O = \ $(STARTUP_FILE) \ - system_stm32f0.o \ + $(SYSTEM_FILE) + +ifeq ($(MCU_SERIES),f0) +SRC_O += \ resethandler_m0.o \ lib/utils/gchelper_m0.o else ifeq ($(MCU_SERIES),l0) CSUPEROPT = -Os # save some code space -SRC_O = \ - $(STARTUP_FILE) \ - lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/system_stm32$(MCU_SERIES)xx.o \ +SRC_O += \ resethandler_m0.o \ lib/utils/gchelper_m0.o else -SRC_O = \ - $(STARTUP_FILE) \ +SRC_O += \ system_stm32.o \ resethandler.o \ lib/utils/gchelper_m3.o diff --git a/ports/stm32/main.c b/ports/stm32/main.c index cd4aaa4845023..c05781432056f 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -368,6 +368,14 @@ STATIC uint update_reset_mode(uint reset_mode) { #endif void stm32_main(uint32_t reset_mode) { + #if !defined(STM32F0) && defined(MICROPY_HW_VTOR) + // Change IRQ vector table if configured differently + SCB->VTOR = MICROPY_HW_VTOR; + #endif + + // Enable 8-byte stack alignment for IRQ handlers, in accord with EABI + SCB->CCR |= SCB_CCR_STKALIGN_Msk; + // Check if bootloader should be entered instead of main application powerctrl_check_enter_bootloader(); diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index be8badea43115..deb23e2f5f0c4 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -75,222 +75,11 @@ ****************************************************************************** */ -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32fxxx_system - * @{ - */ - -/** @addtogroup STM32Fxxx_System_Private_Includes - * @{ - */ - #include "py/mphal.h" #include "powerctrl.h" void __fatal_error(const char *msg); -/** - * @} - */ - -/** @addtogroup STM32Fxxx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32Fxxx_System_Private_Defines - * @{ - */ - -#if defined(STM32F4) || defined(STM32F7) - -#define CONFIG_RCC_CR_1ST (RCC_CR_HSION) -#define CONFIG_RCC_CR_2ND (MICROPY_HW_RCC_CR_HSxON | RCC_CR_CSSON | RCC_CR_PLLON) -#define CONFIG_RCC_PLLCFGR (0x24003010) - -#if defined(STM32F4) -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; -#elif defined(STM32F7) -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; -#endif - -#elif defined(STM32L4) - -#define CONFIG_RCC_CR_1ST (RCC_CR_MSION) -#define CONFIG_RCC_CR_2ND (RCC_CR_HSEON | RCC_CR_CSSON | RCC_CR_HSION | RCC_CR_PLLON) -#define CONFIG_RCC_PLLCFGR (0x00001000) -/* - * FIXME Do not know why I have to define these arrays here! they should be defined in the - * hal_rcc-file!! - * - */ -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; -const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \ - 4000000, 8000000, 16000000, 24000000, 32000000, 48000000}; -#elif defined(STM32H7) - -#define CONFIG_RCC_CR_1ST (RCC_CR_HSION) -#define CONFIG_RCC_CR_2ND (~0xEAF6ED7F) -#define CONFIG_RCC_PLLCFGR (0x00000000) - -#define SRAM_BASE D1_AXISRAM_BASE -#define FLASH_BASE FLASH_BANK1_BASE -uint32_t SystemD2Clock = 64000000; -const uint8_t D1CorePrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; - -#else -#error Unknown processor -#endif - -/************************* Miscellaneous Configuration ************************/ - -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -/* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/******************************************************************************/ - -/** - * @} - */ - -/** @addtogroup STM32Fxxx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32Fxxx_System_Private_Variables - * @{ - */ - /* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock; then there - is no need to call the 2 first functions listed above, since SystemCoreClock - variable is updated automatically. - */ - uint32_t SystemCoreClock = 16000000; - -/** - * @} - */ - -/** @addtogroup STM32Fxxx_System_Private_FunctionPrototypes - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32Fxxx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system - * Initialize the FPU setting, vector table location and External memory - * configuration. - * @param None - * @retval None - */ -void SystemInit(void) -{ - /* FPU settings ------------------------------------------------------------*/ - #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ - #endif - /* Reset the RCC clock configuration to the default reset state ------------*/ - - /* Set configured startup clk source */ - RCC->CR |= CONFIG_RCC_CR_1ST; - - /* Reset CFGR register */ - RCC->CFGR = 0x00000000; - - /* Reset HSxON, CSSON and PLLON bits */ - RCC->CR &= ~ CONFIG_RCC_CR_2ND; - - /* Reset PLLCFGR register */ - RCC->PLLCFGR = CONFIG_RCC_PLLCFGR; - - #if defined(STM32H7) - /* Reset D1CFGR register */ - RCC->D1CFGR = 0x00000000; - - /* Reset D2CFGR register */ - RCC->D2CFGR = 0x00000000; - - /* Reset D3CFGR register */ - RCC->D3CFGR = 0x00000000; - - /* Reset PLLCKSELR register */ - RCC->PLLCKSELR = 0x00000000; - - /* Reset PLL1DIVR register */ - RCC->PLL1DIVR = 0x00000000; - - /* Reset PLL1FRACR register */ - RCC->PLL1FRACR = 0x00000000; - - /* Reset PLL2DIVR register */ - RCC->PLL2DIVR = 0x00000000; - - /* Reset PLL2FRACR register */ - RCC->PLL2FRACR = 0x00000000; - - /* Reset PLL3DIVR register */ - RCC->PLL3DIVR = 0x00000000; - - /* Reset PLL3FRACR register */ - RCC->PLL3FRACR = 0x00000000; - #endif - - /* Reset HSEBYP bit */ - RCC->CR &= (uint32_t)0xFFFBFFFF; - - /* Disable all interrupts */ - #if defined(STM32F4) || defined(STM32F7) - RCC->CIR = 0x00000000; - #elif defined(STM32L4) || defined(STM32H7) - RCC->CIER = 0x00000000; - #endif - - #if defined(STM32H7) - /* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */ - *((__IO uint32_t*)0x51008108) = 0x00000001; - #endif - - /* Configure the Vector Table location add offset address ------------------*/ -#ifdef MICROPY_HW_VTOR - SCB->VTOR = MICROPY_HW_VTOR; -#else -#ifdef VECT_TAB_SRAM - SCB->VTOR = SRAM1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ -#endif -#endif - - /* dpgeorge: enable 8-byte stack alignment for IRQ handlers, in accord with EABI */ - SCB->CCR |= SCB_CCR_STKALIGN_Msk; -} - - /** * @brief System Clock Configuration * diff --git a/ports/stm32/system_stm32f0.c b/ports/stm32/system_stm32f0.c deleted file mode 100644 index 4f561145ccabb..0000000000000 --- a/ports/stm32/system_stm32f0.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * Taken from ST Cube library and modified. See below for original header. - */ - -/** - ****************************************************************************** - * @file system_stm32f0xx.c - * @author MCD Application Team - * @brief CMSIS Cortex-M0 Device Peripheral Access Layer System Source File. - * - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2016 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -#include "py/mphal.h" - -#ifndef HSE_VALUE -#define HSE_VALUE (8000000) -#endif - -#ifndef HSI_VALUE -#define HSI_VALUE (8000000) -#endif - -#ifndef HSI48_VALUE -#define HSI48_VALUE (48000000) -#endif - -/* This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetHCLKFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - Note: If you use this function to configure the system clock there is no need to - call the 2 first functions listed above, since SystemCoreClock variable is - updated automatically. -*/ -uint32_t SystemCoreClock = 8000000; - -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - -void SystemInit(void) { - // Set HSION bit - RCC->CR |= (uint32_t)0x00000001U; - - #if defined(STM32F051x8) || defined(STM32F058x8) - // Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE and MCOSEL[2:0] bits - RCC->CFGR &= (uint32_t)0xF8FFB80CU; - #else - // Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE, MCOSEL[2:0], MCOPRE[2:0] and PLLNODIV bits - RCC->CFGR &= (uint32_t)0x08FFB80CU; - #endif - - // Reset HSEON, CSSON and PLLON bits - RCC->CR &= (uint32_t)0xFEF6FFFFU; - - // Reset HSEBYP bit - RCC->CR &= (uint32_t)0xFFFBFFFFU; - - // Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits - RCC->CFGR &= (uint32_t)0xFFC0FFFFU; - - // Reset PREDIV[3:0] bits - RCC->CFGR2 &= (uint32_t)0xFFFFFFF0U; - - #if defined(STM32F072xB) || defined(STM32F078xx) - // Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits - RCC->CFGR3 &= (uint32_t)0xFFFCFE2CU; - #elif defined(STM32F071xB) - // Reset USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits - RCC->CFGR3 &= (uint32_t)0xFFFFCEACU; - #elif defined(STM32F091xC) || defined(STM32F098xx) - // Reset USART3SW[1:0], USART2SW[1:0], USART1SW[1:0], I2C1SW, CECSW and ADCSW bits - RCC->CFGR3 &= (uint32_t)0xFFF0FEACU; - #elif defined(STM32F030x6) || defined(STM32F030x8) || defined(STM32F031x6) || defined(STM32F038xx) || defined(STM32F030xC) - // Reset USART1SW[1:0], I2C1SW and ADCSW bits - RCC->CFGR3 &= (uint32_t)0xFFFFFEECU; - #elif defined(STM32F051x8) || defined(STM32F058xx) - // Reset USART1SW[1:0], I2C1SW, CECSW and ADCSW bits - RCC->CFGR3 &= (uint32_t)0xFFFFFEACU; - #elif defined(STM32F042x6) || defined(STM32F048xx) - // Reset USART1SW[1:0], I2C1SW, CECSW, USBSW and ADCSW bits - RCC->CFGR3 &= (uint32_t)0xFFFFFE2CU; - #elif defined(STM32F070x6) || defined(STM32F070xB) - // Reset USART1SW[1:0], I2C1SW, USBSW and ADCSW bits - RCC->CFGR3 &= (uint32_t)0xFFFFFE6CU; - // Set default USB clock to PLLCLK, since there is no HSI48 - RCC->CFGR3 |= (uint32_t)0x00000080U; - #else - #warning "No target selected" - #endif - - // Reset HSI14 bit - RCC->CR2 &= (uint32_t)0xFFFFFFFEU; - - // Disable all interrupts - RCC->CIR = 0x00000000U; - - // dpgeorge: enable 8-byte stack alignment for IRQ handlers, in accord with EABI - SCB->CCR |= SCB_CCR_STKALIGN_Msk; -} - -void SystemCoreClockUpdate(void) { - // Get SYSCLK source - uint32_t tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) { - case RCC_CFGR_SWS_HSI: - SystemCoreClock = HSI_VALUE; - break; - case RCC_CFGR_SWS_HSE: - SystemCoreClock = HSE_VALUE; - break; - case RCC_CFGR_SWS_PLL: { - /* Get PLL clock source and multiplication factor */ - uint32_t pllmull = RCC->CFGR & RCC_CFGR_PLLMUL; - uint32_t pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; - pllmull = (pllmull >> 18) + 2; - uint32_t predivfactor = (RCC->CFGR2 & RCC_CFGR2_PREDIV) + 1; - - if (pllsource == RCC_CFGR_PLLSRC_HSE_PREDIV) { - /* HSE used as PLL clock source : SystemCoreClock = HSE/PREDIV * PLLMUL */ - SystemCoreClock = (HSE_VALUE/predivfactor) * pllmull; - #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F072xB) \ - || defined(STM32F078xx) || defined(STM32F091xC) || defined(STM32F098xx) - } else if (pllsource == RCC_CFGR_PLLSRC_HSI48_PREDIV) { - /* HSI48 used as PLL clock source : SystemCoreClock = HSI48/PREDIV * PLLMUL */ - SystemCoreClock = (HSI48_VALUE/predivfactor) * pllmull; - #endif - } else { - #if defined(STM32F042x6) || defined(STM32F048xx) || defined(STM32F070x6) \ - || defined(STM32F078xx) || defined(STM32F071xB) || defined(STM32F072xB) \ - || defined(STM32F070xB) || defined(STM32F091xC) || defined(STM32F098xx) || defined(STM32F030xC) - /* HSI used as PLL clock source : SystemCoreClock = HSI/PREDIV * PLLMUL */ - SystemCoreClock = (HSI_VALUE / predivfactor) * pllmull; - #else - /* HSI used as PLL clock source : SystemCoreClock = HSI/2 * PLLMUL */ - SystemCoreClock = (HSI_VALUE >> 1) * pllmull; - #endif - } - break; - } - case RCC_CFGR_SWS_HSI48: - SystemCoreClock = HSI48_VALUE; - break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - - // Compute HCLK clock frequency - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - SystemCoreClock >>= tmp; -} - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From eea61a09c4b26e8f909bbf52fa9df14f1e2f0390 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 8 Jul 2019 16:08:40 +1000 Subject: [PATCH 0256/1299] stm32/boards/NUCLEO_F446RE: Enable DAC. --- ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h index d801fa18854d3..cd4ad36fa0ee9 100644 --- a/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.h @@ -4,6 +4,7 @@ #define MICROPY_HW_HAS_SWITCH (1) #define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_DAC (1) // HSE is 8MHz, CPU freq set to 168MHz. Using PLLQ for USB this gives a nice // 48 MHz clock for USB. To goto 180 MHz, I think that USB would need to be From 64181b5f767e627591f9684a57bbae19e0415b86 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 20 May 2019 22:00:41 +1000 Subject: [PATCH 0257/1299] stm32: Add support for STM32L452 MCUs. --- ports/stm32/adc.c | 4 +- ports/stm32/boards/stm32l452_af.csv | 85 +++++++++++++++++++++++++++++ ports/stm32/boards/stm32l452xe.ld | 34 ++++++++++++ ports/stm32/dac.c | 14 ++++- ports/stm32/dma.c | 2 + ports/stm32/dma.h | 2 + ports/stm32/flashbdev.c | 6 +- 7 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 ports/stm32/boards/stm32l452_af.csv create mode 100644 ports/stm32/boards/stm32l452xe.ld diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 1215690333809..a4eaefd7589b7 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -145,7 +145,9 @@ #define VBAT_DIV (4) #elif defined(STM32H743xx) #define VBAT_DIV (4) -#elif defined(STM32L432xx) || defined(STM32L475xx) || \ +#elif defined(STM32L432xx) || \ + defined(STM32L451xx) || defined(STM32L452xx) || \ + defined(STM32L462xx) || defined(STM32L475xx) || \ defined(STM32L476xx) || defined(STM32L496xx) #define VBAT_DIV (3) #else diff --git a/ports/stm32/boards/stm32l452_af.csv b/ports/stm32/boards/stm32l452_af.csv new file mode 100644 index 0000000000000..f7170d1c65db5 --- /dev/null +++ b/ports/stm32/boards/stm32l452_af.csv @@ -0,0 +1,85 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,,, +,,SYS_AF,TIM1/TIM2/LPTIM1,I2C4/TIM1/TIM2/TIM3,I2C4/USART2/CAN1/TIM1,I2C1/I2C2/I2C3/I2C4,SPI1/SPI2/I2C4,SPI3/DFSDM/COMP1,USART1/USART2/USART3,UART4/LPUART1/CAN1,CAN1/TSC,CAN1/USB/QUADSPI,,SDMMC1/COMP1/COMP2,SAI1,TIM2/TIM15/TIM16/LPTIM2,EVENTOUT,ADC,COMP,DAC +PortA,PA0,,TIM2_CH1,,,,,,USART2_CTS,UART4_TX,,,,COMP1_OUT,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC12_IN5,COMP1_INM, +PortA,PA1,,TIM2_CH2,,,I2C1_SMBA,SPI1_SCK,,USART2_RTS/USART2_DE,UART4_RX,,,,,,TIM15_CH1N,EVENTOUT,ADC12_IN6,COMP1_INP, +PortA,PA2,,TIM2_CH3,,,,,,USART2_TX,LPUART1_TX,,QUADSPI_BK1_NCS,,COMP2_OUT,,TIM15_CH1,EVENTOUT,ADC12_IN7,COMP2_INM, +PortA,PA3,,TIM2_CH4,,,,,,USART2_RX,LPUART1_RX,,QUADSPI_CLK,,,SAI1_MCLK_A,TIM15_CH2,EVENTOUT,ADC12_IN8,COMP2_INP, +PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS,USART2_CK,,,,,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC12_IN9,COMP1_INM/COMP2_INM,DAC1_OUT1 +PortA,PA5,,TIM2_CH1,TIM2_ETR,,,SPI1_SCK,DFSDM1_CKOUT,,,,,,,,LPTIM2_ETR,EVENTOUT,ADC12_IN10,COMP1_INM/COMP2_INM, +PortA,PA6,,TIM1_BKIN,TIM3_CH1,,,SPI1_MISO,COMP1_OUT,USART3_CTS,LPUART1_CTS,,QUADSPI_BK1_IO3,,TIM1_BKIN_COMP2,,TIM16_CH1,EVENTOUT,ADC12_IN11,, +PortA,PA7,,TIM1_CH1N,TIM3_CH2,,I2C3_SCL,SPI1_MOSI,DFSDM1_DATIN0,,,,QUADSPI_BK1_IO2,,COMP2_OUT,,,EVENTOUT,ADC12_IN12,, +PortA,PA8,MCO,TIM1_CH1,,,,,DFSDM1_CKIN1,USART1_CK,,,,,,SAI1_SCK_A,LPTIM2_OUT,EVENTOUT,,, +PortA,PA9,,TIM1_CH2,,,I2C1_SCL,,DFSDM1_DATIN1,USART1_TX,,,,,,SAI1_FS_A,TIM15_BKIN,EVENTOUT,,, +PortA,PA10,,TIM1_CH3,,,I2C1_SDA,,,USART1_RX,,,USBCRS_SYNC,,,SAI1_SD_A,,EVENTOUT,,, +PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,COMP1_OUT,USART1_CTS,,CAN1_RX,USBDM,,TIM1_BKIN2_COMP1,,,EVENTOUT,,, +PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS/USART1_DE,,CAN1_TX,USBDP,,,,,EVENTOUT,,, +PortA,PA13,JTMS/SWDIO,IR_OUT,,,,,,,,,USBNOE,,,SAI1_SD_B,,EVENTOUT,,, +PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,I2C4_SMBA,,,,,,,,SAI1_FS_B,,EVENTOUT,,, +PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,USART2_RX,,SPI1_NSS,SPI3_NSS,USART3_RTS/USART3_DE,UART4_RTS/UART4_DE,TSC_G3_IO1,,,,,,EVENTOUT,,, +PortB,PB0,,TIM1_CH2N,TIM3_CH3,,,SPI1_NSS,DFSDM1_CKIN0,USART3_CK,,,QUADSPI_BK1_IO1,,COMP1_OUT,SAI1_EXTCLK,,EVENTOUT,ADC12_IN15,, +PortB,PB1,,TIM1_CH3N,TIM3_CH4,,,,DFSDM_DATIN0,USART3_RTS/USART3_DE,LPUART1_RTS/LPUART1_DE,,QUADSPI_BK1_IO0,,,,LPTIM2_IN1,EVENTOUT,ADC12_IN16,COMP1_INN, +PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,,DFSDM_CKIN0,,,,,,,,,EVENTOUT,,COMP1_INP, +PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK,USART1_RTS/USART1_DE,,,,,,SAI1_SCK_B,,EVENTOUT,,COMP2_INM, +PortB,PB4,NJTRST,,TIM3_CH1,,I2C3_SDA,SPI1_MISO,SPI3_MISO,USART1_CTS,,TSC_G2_IO1,,,,SAI1_MCLK_B,,EVENTOUT,,COMP2_INP, +PortB,PB5,,LPTIM1_IN1,TIM3_CH2,CAN1_RX,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI,USART1_CK,,TSC_G2_IO2,,,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT,,, +PortB,PB6,,LPTIM1_ETR,,,I2C1_SCL,I2C4_SCL,,USART1_TX,CAN1_TX,TSC_G2_IO3,,,,SAI1_FS_B,TIM16_CH1N,EVENTOUT,,COMP2_INP, +PortB,PB7,,LPTIM1_IN2,,,I2C1_SDA,I2C4_SDA,,USART1_RX,UART4_CTS,TSC_G2_IO4,,,,,,EVENTOUT,,COMP2_INM, +PortB,PB8,,,,,I2C1_SCL,,,,,CAN1_RX,,,SDMMC1_D4,SAI1_MCLK_A,TIM16_CH1,EVENTOUT,,, +PortB,PB9,,IR_OUT,,,I2C1_SDA,SPI2_NSS,,,,CAN1_TX,,,SDMMC1_D5,SAI1_FS_A,,EVENTOUT,,, +PortB,PB10,,TIM2_CH3,,I2C4_SCL,I2C2_SCL,SPI2_SCK,,USART3_TX,LPUART1_RX,TSC_SYNC,QUADSPI_CLK,,COMP1_OUT,SAI1_SCK_A,,EVENTOUT,,, +PortB,PB11,,TIM2_CH4,,I2C4_SDA,I2C2_SDA,,,USART3_RX,LPUART1_TX,,QUADSPI_NCS,,COMP2_OUT,,,EVENTOUT,,, +PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM_DATIN1,USART3_CK,LPUART1_RTS/LPUART1_DE,TSC_G1_IO1,CAN1_RX,,,SAI1_FS_A,TIM15_BKIN,EVENTOUT,,, +PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,CAN1_TX,,,SAI1_SCK_A,TIM15_CH1N,EVENTOUT,,, +PortB,PB14,,TIM1_CH2N,,,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS_DE,,TSC_G1_IO3,,,,SAI1_MCLK_A,TIM15_CH1,EVENTOUT,,, +PortB,PB15,RTC_REFIN,TIM1_CH3N,,,,SPI2_MOSI,DFSDM_CKIN2,,,TSC_G1_IO4,,,,SAI1_SD_A,TIM15_CH2,EVENTOUT,,, +PortC,PC0,,LPTIM1_IN1,I2C4_SCL,,I2C3_SCL,,,,LPUART1_RX,,,,,,LPTIM2_IN1,EVENTOUT,ADC123_IN1,, +PortC,PC1,TRACED0,LPTIM1_OUT,I2C4_SDA,,I2C3_SDA,,,,LPUART1_TX,,,,,,,EVENTOUT,ADC123_IN2,, +PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,DFSDM_CKOUT,,,,,,,,,EVENTOUT,ADC123_IN3,, +PortC,PC3,,LPTIM1_ETR,,,,SPI2_MOSI,,,,,,,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC123_IN4,, +PortC,PC4,,,,,,,,USART3_TX,,,,,,,,EVENTOUT,ADC12_IN13,COMP1_INM, +PortC,PC5,,,,,,,,USART3_RX,,,,,,,,EVENTOUT,ADC12_IN14,COMP1_INP, +PortC,PC6,,,TIM3_CH1,,,,DFSDM_CKIN3,,,TSC_G4_IO1,,,SDMMC1_D6,,,EVENTOUT,,, +PortC,PC7,,,TIM3_CH2,,,,DFSDM_DATIN3,,,TSC_G4_IO2,,,SDMMC1_D7,,,EVENTOUT,,, +PortC,PC8,,,TIM3_CH3,,,,,,,TSC_G4_IO3,,,SDMMC1_D0,,,EVENTOUT,,, +PortC,PC9,,,TIM3_CH4,,,,,,,TSC_G4_IO4,USBNOE,,SDMMC1_D1,,,EVENTOUT,,, +PortC,PC10,TRACED1,,,,,,SPI3_SCK,USART3_TX,UART4_TX,TSC_G3_IO2,,,SDMMC1_D2,,,EVENTOUT,,, +PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,TSC_G3_IO3,,,SDMMC1_D3,,,EVENTOUT,,, +PortC,PC12,TRACED3,,,,,,SPI3_MOSI,USART3_CK,,TSC_G3_IO4,,,SDMMC1_CK,,,EVENTOUT,,, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,,, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,,, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,,, +PortD,PD0,,,,,,SPI2_NSS,,,,CAN1_RX,,,,,,EVENTOUT,,, +PortD,PD1,,,,,,SPI2_SCK,,,,CAN1_TX,,,,,,EVENTOUT,,, +PortD,PD2,TRACED2,,TIM3_ETR,,,,,USART3_RTS/USART3_DE,,TSC_SYNC,,,SDMMC1_CMD,,,EVENTOUT,,, +PortD,PD3,,,,,,SPI2_MISO,DFSDM_DATIN0,USART2_CTS,,,QUADSPI_BK2_NCS,,,,,EVENTOUT,,, +PortD,PD4,,,,,,SPI2_MOSI,DFSDM_CKIN0,USART2_RTS/USART2_DE,,,QUADSPI_BK2_IO0,,,,,EVENTOUT,,, +PortD,PD5,,,,,,,,USART2_TX,,,QUADSPI_BK2_IO1,,,,,EVENTOUT,,, +PortD,PD6,,,,,,,DFSDM_DATIN1,USART2_RX,,,QUADSPI_BK2_IO2,,,SAI1_SD_A,,EVENTOUT,,, +PortD,PD7,,,,,,,DFSDM_CKIN1,USART2_CK,,,QUADSPI_BK2_IO3,,,,,EVENTOUT,,, +PortD,PD8,,,,,,,,USART3_TX,,,,,,,,EVENTOUT,,, +PortD,PD9,,,,,,,,USART3_RX,,,,,,,,EVENTOUT,,, +PortD,PD10,,,,,,,,USART3_CK,,TSC_G6_IO1,,,,,,EVENTOUT,,, +PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,TSC_G6_IO2,,,,,LPTIM2_ETR,EVENTOUT,,, +PortD,PD12,,,,,I2C4_SCL,,,USART3_RTS/USART3_DE,,TSC_G6_IO3,,,,,LPTIM2_IN1,EVENTOUT,,, +PortD,PD13,,,,,I2C4_SDA,,,,,TSC_G6_IO4,,,,,LPTIM2_OUT,EVENTOUT,,, +PortD,PD14,,,,,,,,,,,,,,,,EVENTOUT,,, +PortD,PD15,,,,,,,,,,,,,,,,EVENTOUT,,, +PortE,PE0,,,,,,,,,,,,,,,TIM16_CH1,EVENTOUT,,, +PortE,PE1,,,,,,,,,,,,,,,,EVENTOUT,,, +PortE,PE2,TRACECLK,,TIM3_ETR,,,,,,,TSC_G7_IO1,,,,SAI1_MCLK_A,,EVENTOUT,,, +PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,TSC_G7_IO2,,,,SAI1_SD_B,,EVENTOUT,,, +PortE,PE4,TRACED1,,TIM3_CH2,,,,DFSDM_DATIN3,,,TSC_G7_IO3,,,,SAI1_FS_A,,EVENTOUT,,, +PortE,PE5,TRACED2,,TIM3_CH3,,,,DFSDM_CKIN3,,,TSC_G7_IO4,,,,SAI1_SCK_A,,EVENTOUT,,, +PortE,PE6,TRACED3,,TIM3_CH4,,,,,,,,,,,SAI1_SD_A,,EVENTOUT,,, +PortE,PE7,,TIM1_ETR,,,,,DFSDM_DATIN2,,,,,,,SAI1_SD_B,,EVENTOUT,,, +PortE,PE8,,TIM1_CH1N,,,,,DFSDM_CKIN2,,,,,,,SAI1_SCK_B,,EVENTOUT,,, +PortE,PE9,,TIM1_CH1,,,,,DFSDM_CKOUT,,,,,,,SAI1_FS_B,,EVENTOUT,,, +PortE,PE10,,TIM1_CH2N,,,,,,,,TSC_G5_IO1,QUADSPI_CLK,,,SAI1_MCLK_B,,EVENTOUT,,, +PortE,PE11,,TIM1_CH2,,,,,,,,TSC_G5_IO2,QUADSPI_BK1_NCS,,,,,EVENTOUT,,, +PortE,PE12,,TIM1_CH3N,,,,SPI1_NSS,,,,TSC_G5_IO3,QUADSPI_BK1_IO0,,,,,EVENTOUT,,, +PortE,PE13,,TIM1_CH3,,,,SPI1_SCK,,,,TSC_G5_IO4,QUADSPI_BK1_IO1,,,,,EVENTOUT,,, +PortE,PE14,,TIM1_CH4,TIM1_BKIN2,TIM1_BKIN2_COMP2,,SPI1_MISO,,,,,QUADSPI_BK1_IO2,,,,,EVENTOUT,,, +PortE,PE15,,TIM1_BKIN,,TIM1_BKIN_COMP1,,SPI1_MOSI,,,,,QUADSPI_BK1_IO3,,,,,EVENTOUT,,, +PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,,, +PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,,, +PortH,PH3,,,,,,,,,,,,,,,,,,, diff --git a/ports/stm32/boards/stm32l452xe.ld b/ports/stm32/boards/stm32l452xe.ld new file mode 100644 index 0000000000000..7b07ee7018dd8 --- /dev/null +++ b/ports/stm32/boards/stm32l452xe.ld @@ -0,0 +1,34 @@ +/* + GNU linker script for STM32L452XE +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K /* sectors 0-191 */ + FLASH_FS (r) : ORIGIN = 0x08060000, LENGTH = 128K /* sectors 192-255 */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 160K /* SRAM1, 128K + SRAM2, 32K */ +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* Define the stack. The stack is full descending so begins just above last byte of RAM, + or bottom of FS cache.. Note that EABI requires the stack to be 8-byte aligned for a call. */ + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_ram_fs_cache_end = _ram_end; +_ram_fs_cache_start = _ram_fs_cache_end - 2K; /* fs cache = 2K */ + +_estack = _ram_fs_cache_start - _estack_reserve; +_sstack = _estack - 16K; /* stack = 16K */ + +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _sstack; /* bss + heap = 142K, tunable by adjusting stack size */ + +_flash_fs_start = ORIGIN(FLASH_FS); +_flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index cb9157c3daa97..f3dcccb3da251 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -148,8 +148,10 @@ STATIC void dac_set_value(uint32_t dac_channel, uint32_t align, uint32_t value) uint32_t base; if (dac_channel == DAC_CHANNEL_1) { base = (uint32_t)&DAC->DHR12R1; + #if !defined(STM32L452xx) } else { base = (uint32_t)&DAC->DHR12R2; + #endif } *(volatile uint32_t*)(base + align) = value; } @@ -169,8 +171,10 @@ STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, ui uint32_t base; if (dac_channel == DAC_CHANNEL_1) { base = (uint32_t)&DAC->DHR12R1; + #if !defined(STM32L452xx) } else { base = (uint32_t)&DAC->DHR12R2; + #endif } dma_nohal_deinit(dma_descr); @@ -185,7 +189,7 @@ STATIC void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, ui typedef struct _pyb_dac_obj_t { mp_obj_base_t base; - uint8_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2 + uint8_t dac_channel; // DAC_CHANNEL_1 or DAC_CHANNEL_2. STM32L452 only has CHANNEL_1. uint8_t bits; // 8 or 12 uint8_t outbuf_single; uint8_t outbuf_waveform; @@ -200,8 +204,10 @@ STATIC void pyb_dac_reconfigure(pyb_dac_obj_t *self, uint32_t cr, uint32_t outbu const dma_descr_t *tx_dma_descr; if (self->dac_channel == DAC_CHANNEL_1) { tx_dma_descr = &dma_DAC_1_TX; + #if !defined(STM32L452xx) } else { tx_dma_descr = &dma_DAC_2_TX; + #endif } dma_nohal_deinit(tx_dma_descr); dac_config_channel(self->dac_channel, cr, outbuf); @@ -234,8 +240,10 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp mp_hal_pin_obj_t pin; if (self->dac_channel == DAC_CHANNEL_1) { pin = pin_A4; + #if !defined(STM32L452xx) } else { pin = pin_A5; + #endif } mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0); @@ -306,8 +314,10 @@ STATIC mp_obj_t pyb_dac_make_new(const mp_obj_type_t *type, size_t n_args, size_ uint32_t dac_channel; if (dac_id == 1) { dac_channel = DAC_CHANNEL_1; + #if !defined(STM32L452xx) } else if (dac_id == 2) { dac_channel = DAC_CHANNEL_2; + #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "DAC(%d) doesn't exist", dac_id)); } @@ -446,8 +456,10 @@ mp_obj_t pyb_dac_write_timed(size_t n_args, const mp_obj_t *pos_args, mp_map_t * const dma_descr_t *tx_dma_descr; if (self->dac_channel == DAC_CHANNEL_1) { tx_dma_descr = &dma_DAC_1_TX; + #if !defined(STM32L452xx) } else { tx_dma_descr = &dma_DAC_2_TX; + #endif } uint32_t align; diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 32b9a74d709a3..2c7371e010e64 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -387,7 +387,9 @@ const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_3, dma_id_5, &dm const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_3, dma_id_6, &dma_init_struct_spi_i2c }; // DMA2 streams +const dma_descr_t dma_I2C_4_RX = { DMA2_Channel1, DMA_REQUEST_0, dma_id_0, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_3_RX = { DMA2_Channel1, DMA_REQUEST_3, dma_id_7, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_4_TX = { DMA2_Channel2, DMA_REQUEST_0, dma_id_1, &dma_init_struct_spi_i2c }; const dma_descr_t dma_SPI_3_TX = { DMA2_Channel2, DMA_REQUEST_3, dma_id_8, &dma_init_struct_spi_i2c }; /* not preferred streams const dma_descr_t dma_ADC_1_RX = { DMA2_Channel3, DMA_REQUEST_0, dma_id_9, NULL }; diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index bedabe7f89251..6d07a94ed99af 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -93,6 +93,8 @@ extern const dma_descr_t dma_I2C_1_RX; extern const dma_descr_t dma_SPI_3_RX; extern const dma_descr_t dma_SPI_3_TX; extern const dma_descr_t dma_SDIO_0; +extern const dma_descr_t dma_I2C_4_TX; +extern const dma_descr_t dma_I2C_4_RX; #endif diff --git a/ports/stm32/flashbdev.c b/ports/stm32/flashbdev.c index 484fa1a1bc0ab..0a5f417040f9f 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -103,9 +103,11 @@ STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k #define FLASH_MEM_SEG1_START_ADDR (0x08020000) // sector 1 #define FLASH_MEM_SEG1_NUM_BLOCKS (256) // Sector 1: 128k / 512b = 256 blocks -#elif defined(STM32L432xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) +#elif defined(STM32L432xx) || \ + defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) -// The STM32L475/6 doesn't have CCRAM, so we use the 32K SRAM2 for this, although +// The STM32L4xx doesn't have CCRAM, so we use SRAM2 for this, although // actual location and size is defined by the linker script. extern uint8_t _flash_fs_start; extern uint8_t _flash_fs_end; From c24d81119c4e34936e2c8be1e7c7aa79a71e0d14 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Sat, 29 Jun 2019 20:55:19 +1000 Subject: [PATCH 0258/1299] stm32/boards/NUCLEO_L452RE: Add definition files for new board. --- .../boards/NUCLEO_L452RE/mpconfigboard.h | 74 ++++++++++++++++ .../boards/NUCLEO_L452RE/mpconfigboard.mk | 5 ++ ports/stm32/boards/NUCLEO_L452RE/pins.csv | 86 +++++++++++++++++++ .../boards/NUCLEO_L452RE/stm32l4xx_hal_conf.h | 20 +++++ 4 files changed, 185 insertions(+) create mode 100644 ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h create mode 100644 ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.mk create mode 100644 ports/stm32/boards/NUCLEO_L452RE/pins.csv create mode 100644 ports/stm32/boards/NUCLEO_L452RE/stm32l4xx_hal_conf.h diff --git a/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h new file mode 100644 index 0000000000000..9823ae9b9b74d --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.h @@ -0,0 +1,74 @@ +#define MICROPY_HW_BOARD_NAME "NUCLEO-L452RE" +#define MICROPY_HW_MCU_NAME "STM32L452RE" + +#define MICROPY_PY_USOCKET (0) +#define MICROPY_PY_NETWORK (0) + +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_SERVO (0) // SERVO requires TIM5 (not on L452). +#define MICROPY_HW_HAS_SWITCH (1) + +// MSI is used and is 4MHz +#define MICROPY_HW_CLK_PLLM (1) +#define MICROPY_HW_CLK_PLLN (40) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) +#define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) +#define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 + +// The board has an external 32kHz crystal +#define MICROPY_HW_RTC_USE_LSE (1) + +// UART config +#define MICROPY_HW_UART1_TX (pin_B6) +#define MICROPY_HW_UART1_RX (pin_B7) +#define MICROPY_HW_UART2_TX (pin_A2) // VCP TX +#define MICROPY_HW_UART2_RX (pin_A3) // VCP RX +#define MICROPY_HW_UART3_TX (pin_C10) +#define MICROPY_HW_UART3_RX (pin_C11) +#define MICROPY_HW_UART4_TX (pin_A0) +#define MICROPY_HW_UART4_RX (pin_A1) +// USART2 is connected to the ST-LINK USB VCP +#define MICROPY_HW_UART_REPL PYB_UART_2 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C busses +#define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 +#define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino D14, pin 5 on CN10 +#define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10 +#define MICROPY_HW_I2C2_SDA (pin_B11) // pin 18 on CN10 +#define MICROPY_HW_I2C3_SCL (pin_A7) // pin 15 on CN10 +#define MICROPY_HW_I2C3_SDA (pin_B4) // pin 27 on CN10 +#define MICROPY_HW_I2C4_SCL (pin_C0) // pin 38 on CN7 +#define MICROPY_HW_I2C4_SDA (pin_C1) // pin 36 on CN7 + +// SPI busses +#define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7 +#define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 +#define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 +#define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 +#define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 +#define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 +#define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 +#define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 +#define MICROPY_HW_SPI3_NSS (pin_A4) // pin 32 on CN7 +#define MICROPY_HW_SPI3_SCK (pin_C10) // pin 1 on CN7 +#define MICROPY_HW_SPI3_MISO (pin_C11) // pin 2 on CN7 +#define MICROPY_HW_SPI3_MOSI (pin_C12) // pin 3 on CN7 + +// CAN busses +#define MICROPY_HW_CAN1_TX (pin_B9) +#define MICROPY_HW_CAN1_RX (pin_B8) + +// USER B1 has a pull-up and is active low +#define MICROPY_HW_USRSW_PIN (pin_C13) +#define MICROPY_HW_USRSW_PULL (0) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// NUCLEO-64 has one user LED +#define MICROPY_HW_LED1 (pin_A5) // green +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) diff --git a/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.mk new file mode 100644 index 0000000000000..25ccb45a9427e --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L452RE/mpconfigboard.mk @@ -0,0 +1,5 @@ +MCU_SERIES = l4 +CMSIS_MCU = STM32L452xx +AF_FILE = boards/stm32l452_af.csv +LD_FILES = boards/stm32l452xe.ld boards/common_basic.ld +OPENOCD_CONFIG = boards/openocd_stm32l4.cfg diff --git a/ports/stm32/boards/NUCLEO_L452RE/pins.csv b/ports/stm32/boards/NUCLEO_L452RE/pins.csv new file mode 100644 index 0000000000000..adc319575ac07 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L452RE/pins.csv @@ -0,0 +1,86 @@ +CN9_D0,PA3 +CN9_D1,PA2 +CN9_D2,PA10 +CN9_D3,PB3 +CN9_D4,PB5 +CN9_D5,PB4 +CN9_D6,PB10 +CN9_D7,PA8 +CN5_D8,PA9 +CN5_D9,PC7 +CN5_D10,PB6 +CN5_D11,PA7 +CN5_D12,PA6 +CN5_D13,PA5 +CN5_D14,PB9 +CN5_D15,PB8 +CN8_A0,PA0 +CN8_A1,PA1 +CN8_A2,PA4 +CN8_A3,PB0 +CN8_A4,PC1 +CN8_A5,PC0 +CN9_RX,PA3 +CN9_TX,PA2 +CN5_SCL,PB8 +CN5_SDA,PB9 +CN5_SCK,PA5 +CN5_MISO,PA6 +CN5_MOSI,PA7 +CN5_CS,PB6 +CN7_28,PA0 +CN7_30,PA1 +CN10_35,PA2 +CN10_37,PA3 +CN7_32,PA4 +CN10_11,PA5 +CN10_13,PA6 +CN10_15,PA7 +CN10_23,PA8 +CN10_21,PA9 +CN10_33,PA10 +CN10_14,PA11 +CN10_12,PA12 +CN7_13,PA13 +CN7_15,PA14 +CN7_17,PA15 +CN7_34,PB0 +CN10_24,PB1 +CN10_22,PB2 +CN10_31,PB3 +CN10_27,PB4 +CN10_29,PB5 +CN10_17,PB6 +CN7_21,PB7 +CN10_3,PB8 +CN10_5,PB9 +CN10_25,PB10 +CN10_18,PB11 +CN10_16,PB12 +CN10_30,PB13 +CN10_28,PB14 +CN10_26,PB15 +CN7_38,PC0 +CN7_36,PC1 +CN7_35,PC2 +CN7_37,PC3 +CN10_34,PC4 +CN10_6,PC5 +CN10_4,PC6 +CN10_19,PC7 +CN10_2,PC8 +CN10_1,PC9 +CN7_1,PC10 +CN7_2,PC11 +CN7_3,PC12 +CN7_23,PC13 +CN7_25,PC14 +CN7_27,PC15 +CN7_4,PD2 +CN7_29,PH0 +CN7_31,PH1 +BOOT0,PH3 +SWDIO,PA13 +SWCLK,PA14 +USER_B1,PC13 +LED_GREEN,PA5 diff --git a/ports/stm32/boards/NUCLEO_L452RE/stm32l4xx_hal_conf.h b/ports/stm32/boards/NUCLEO_L452RE/stm32l4xx_hal_conf.h new file mode 100644 index 0000000000000..fd380ab7357e2 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_L452RE/stm32l4xx_hal_conf.h @@ -0,0 +1,20 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H + +#include "boards/stm32l4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) +#define EXTERNAL_SAI2_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L4XX_HAL_CONF_H From d43dd886a5d072f49d5c27779199f3e233d6afb5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 11:32:12 +1000 Subject: [PATCH 0259/1299] stm32/boards/NUCLEO_F413ZH: Remove STARTUP_FILE, it's defined globally. The Makefile now defines this variable to the correct value (but it can still be overridden by a board if necessary). --- ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk index efc05dba843b5..7d8ea6bf6bbb0 100644 --- a/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F413ZH/mpconfigboard.mk @@ -1,6 +1,5 @@ MCU_SERIES = f4 CMSIS_MCU = STM32F413xx -STARTUP_FILE = boards/startup_stm32f413xx.o AF_FILE = boards/stm32f413_af.csv LD_FILES = boards/stm32f413xh.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 From c8f19f13715ca201815a8594e32121ae06f504c5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 11:33:57 +1000 Subject: [PATCH 0260/1299] stm32/mboot: Make _estack an array to avoid compiler warnings. The compiler can warn about out-of-bounds array access if _estack is just a single uint8_t. --- ports/stm32/mboot/mboot.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/stm32/mboot/mboot.h b/ports/stm32/mboot/mboot.h index 54b3dc7298aca..7dc1ada0c32f6 100644 --- a/ports/stm32/mboot/mboot.h +++ b/ports/stm32/mboot/mboot.h @@ -30,8 +30,9 @@ // Use this to tag global static data in RAM that doesn't need to be zeroed on startup #define SECTION_NOZERO_BSS __attribute__((section(".nozero_bss"))) -#define ELEM_DATA_START (&_estack) -#define ELEM_DATA_MAX (ELEM_DATA_START + 1024) +#define ELEM_DATA_SIZE (1024) +#define ELEM_DATA_START (&_estack[0]) +#define ELEM_DATA_MAX (&_estack[ELEM_DATA_SIZE]) enum { ELEM_TYPE_END = 1, @@ -48,7 +49,7 @@ typedef struct _fsload_bdev_t { uint32_t byte_len; } fsload_bdev_t; -extern uint8_t _estack; +extern uint8_t _estack[ELEM_DATA_SIZE]; uint32_t get_le32(const uint8_t *b); void led_state_all(unsigned int mask); From 5a81d2d6b895e538909ca5bc66adf39ed412c7f3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 11:34:54 +1000 Subject: [PATCH 0261/1299] stm32/mboot: Remove use of BSRRL/H for H7 MCUs due to stm32lib update. --- ports/stm32/mboot/mphalport.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ports/stm32/mboot/mphalport.h b/ports/stm32/mboot/mphalport.h index 69ca0b035b5bc..86063c4ef2438 100644 --- a/ports/stm32/mboot/mphalport.h +++ b/ports/stm32/mboot/mphalport.h @@ -48,13 +48,8 @@ #define mp_hal_pin_input(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_output(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0) #define mp_hal_pin_open_drain(p) mp_hal_pin_config((p), MP_HAL_PIN_MODE_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 0) -#if defined(STM32H7) -#define mp_hal_pin_low(p) (((GPIO_TypeDef*)((p) & ~0xf))->BSRRH = 1 << ((p) & 0xf)) -#define mp_hal_pin_high(p) (((GPIO_TypeDef*)((p) & ~0xf))->BSRRL = 1 << ((p) & 0xf)) -#else #define mp_hal_pin_low(p) (((GPIO_TypeDef*)((p) & ~0xf))->BSRR = 0x10000 << ((p) & 0xf)) #define mp_hal_pin_high(p) (((GPIO_TypeDef*)((p) & ~0xf))->BSRR = 1 << ((p) & 0xf)) -#endif #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_read(p) ((((GPIO_TypeDef*)((p) & ~0xf))->IDR >> ((p) & 0xf)) & 1) From 342539bdcce5b00b53e01423bc57782d65d5ff4b Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 11:35:47 +1000 Subject: [PATCH 0262/1299] stm32/mboot: Use STARTUP_FILE from stm32lib. --- ports/stm32/mboot/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 0a5759347f74d..689daed54a64d 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -20,8 +20,10 @@ endif include ../../../py/mkenv.mk include $(BOARD_DIR)/mpconfigboard.mk -CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include MCU_SERIES_UPPER = $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') +CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]') + +CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include HAL_DIR=lib/stm32lib/STM32$(MCU_SERIES_UPPER)xx_HAL_Driver USBDEV_DIR=usbdev DFU=$(TOP)/tools/dfu.py @@ -30,6 +32,7 @@ DEVICE=0483:df11 STFLASH ?= st-flash OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg +STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o CROSS_COMPILE = arm-none-eabi- @@ -101,7 +104,7 @@ SRC_C = \ $(wildcard $(BOARD_DIR)/*.c) SRC_O = \ - ports/stm32/boards/startup_stm32$(MCU_SERIES).o \ + $(STARTUP_FILE) \ ports/stm32/resethandler.o \ $(BUILD)/$(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_ll_usb.o: CFLAGS += -Wno-attributes From 278e9bffe9e6acf9072a5428af0ba3e61896e7a5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 11:46:47 +1000 Subject: [PATCH 0263/1299] stm32/mboot: Update dependencies to enable parallel build with -j. --- ports/stm32/mboot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 689daed54a64d..f2c3baecc1a6b 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -178,7 +178,7 @@ GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h GEN_PINS_AF_PY = $(BUILD)/pins_af.py -$(BUILD)/main.o: $(GEN_QSTRDEFS_GENERATED) $(GEN_PINS_AF_DEFS) +$(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_PINS_AF_DEFS) $(HEADER_BUILD): $(MKDIR) -p $(BUILD)/genhdr From 14f61a224dd138b48623f16ed5a56e6244c7bffe Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 11:47:57 +1000 Subject: [PATCH 0264/1299] travis: Build stm32 mboot for PYBD_SF6 as part of CI. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 284d311f7e112..0088fbe90d1b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,6 +39,7 @@ jobs: - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32F769DISC - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32L476DISC + - make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBD_SF6 # qemu-arm port - stage: test From a17b901a9ea8f2dfe2db0822cdcd47b9c719a90a Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 12:54:09 +1000 Subject: [PATCH 0265/1299] stm32/boards/B_L072Z_LRWAN1: Add definition files for new board. --- .../boards/B_L072Z_LRWAN1/mpconfigboard.h | 60 +++++++++++++++++++ .../boards/B_L072Z_LRWAN1/mpconfigboard.mk | 7 +++ ports/stm32/boards/B_L072Z_LRWAN1/pins.csv | 51 ++++++++++++++++ .../B_L072Z_LRWAN1/stm32l0xx_hal_conf.h | 18 ++++++ 4 files changed, 136 insertions(+) create mode 100644 ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h create mode 100644 ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk create mode 100644 ports/stm32/boards/B_L072Z_LRWAN1/pins.csv create mode 100644 ports/stm32/boards/B_L072Z_LRWAN1/stm32l0xx_hal_conf.h diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h new file mode 100644 index 0000000000000..da219abd30d38 --- /dev/null +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h @@ -0,0 +1,60 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * MIT License; Copyright (c) 2019 Damien P. George + */ + +#define MICROPY_HW_BOARD_NAME "B-L072Z-LRWAN1" +#define MICROPY_HW_MCU_NAME "STM32L072CZ" + +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_PY_BUILTINS_COMPLEX (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_FRAMEBUF (0) +#define MICROPY_PY_USOCKET (0) +#define MICROPY_PY_NETWORK (0) +#define MICROPY_PY_STM (0) +#define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_VFS_FAT (0) + +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_ADC (0) +#define MICROPY_HW_HAS_SWITCH (1) + +// UART config +#define MICROPY_HW_UART1_TX (pin_A9) +#define MICROPY_HW_UART1_RX (pin_A10) +#define MICROPY_HW_UART2_TX (pin_A2) +#define MICROPY_HW_UART2_RX (pin_A3) + +// USART2 is connected to the ST-LINK USB VCP +#define MICROPY_HW_UART_REPL PYB_UART_2 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C busses +#define MICROPY_HW_I2C1_SCL (pin_B8) +#define MICROPY_HW_I2C1_SDA (pin_B9) + +// SPI busses +#define MICROPY_HW_SPI1_NSS (pin_A15) +#define MICROPY_HW_SPI1_SCK (pin_A5) +#define MICROPY_HW_SPI1_MISO (pin_A6) +#define MICROPY_HW_SPI1_MOSI (pin_A7) +#define MICROPY_HW_SPI2_NSS (pin_B12) +#define MICROPY_HW_SPI2_SCK (pin_B13) +#define MICROPY_HW_SPI2_MISO (pin_B14) +#define MICROPY_HW_SPI2_MOSI (pin_B15) + +// USER B1 has a pull-up and is active low +#define MICROPY_HW_USRSW_PIN (pin_B2) +#define MICROPY_HW_USRSW_PULL (0) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// 4 user LEDs +#define MICROPY_HW_LED1 (pin_B5) // Green +#define MICROPY_HW_LED2 (pin_A5) // Green (next to power LED) +#define MICROPY_HW_LED3 (pin_B6) // Blue +#define MICROPY_HW_LED4 (pin_B7) // Red +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk new file mode 100644 index 0000000000000..a39a2bd47b378 --- /dev/null +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk @@ -0,0 +1,7 @@ +MCU_SERIES = l0 +CMSIS_MCU = STM32L072xx +AF_FILE = boards/stm32l072_af.csv +LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld + +# Don't include default frozen modules because MCU is tight on flash space +FROZEN_MPY_DIR ?= diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/pins.csv b/ports/stm32/boards/B_L072Z_LRWAN1/pins.csv new file mode 100644 index 0000000000000..e54b8b818a89e --- /dev/null +++ b/ports/stm32/boards/B_L072Z_LRWAN1/pins.csv @@ -0,0 +1,51 @@ +D0,PA3 +D1,PA2 +D2,PA10 +D3,PB13 +D4,PB5 +D5,PB7 +D6,PB2 +D7,PA8 +D8,PA9 +D9,PB12 +D10,PB6 +D11,PB15 +D12,PB14 +D13,PB13 +D14,PB9 +D15,PB8 +A0,PA0 +A2,PA4 +USER_B1,PB2 +LED2,PA5 +LED1,PB5 +LED3,PB6 +LED4,PB7 +LED_GREEN,PB5 +LED_BLUE,PB6 +LED_RED,PB7 +,PA0 +,PA2 +,PA3 +,PA4 +,PA5 +,PA6 +,PA7 +,PA8 +,PA9 +,PA10 +,PA11 +,PA12 +,PA13 +,PA14 +,PA15 +,PB2 +,PB5 +,PB6 +,PB7 +,PB8 +,PB9 +,PB12 +,PB13 +,PB14 +,PB15 diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/stm32l0xx_hal_conf.h b/ports/stm32/boards/B_L072Z_LRWAN1/stm32l0xx_hal_conf.h new file mode 100644 index 0000000000000..c88a7065103d3 --- /dev/null +++ b/ports/stm32/boards/B_L072Z_LRWAN1/stm32l0xx_hal_conf.h @@ -0,0 +1,18 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H + +#include "boards/stm32l0xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32L0XX_HAL_CONF_H From 42d30c5bafc4d1d94787257eedf5c845423658f1 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Fri, 5 Jul 2019 12:06:16 +0200 Subject: [PATCH 0266/1299] unix/unix_mphal: Include time.h for CLOCK_MONOTONIC. --- ports/unix/unix_mphal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 71edaa57acfbc..9b009dc5021e1 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "py/mphal.h" From a1c870e9f4562e1c1fd056653ff49efdda8bd840 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Mon, 8 Jul 2019 09:45:02 +0200 Subject: [PATCH 0267/1299] javascript: Enable support for frozen bytecode via FROZEN_MPY_DIR. --- ports/javascript/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/javascript/Makefile b/ports/javascript/Makefile index 7309dfa481320..384253e5449f5 100644 --- a/ports/javascript/Makefile +++ b/ports/javascript/Makefile @@ -25,6 +25,13 @@ LDFLAGS = -m32 -Wl,-Map=$@.map,--cref -Wl,--gc-sections CFLAGS += -O0 -DNDEBUG CFLAGS += -fdata-sections -ffunction-sections +ifneq ($(FROZEN_MPY_DIR),) +# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and +# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). +CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool +CFLAGS += -DMICROPY_MODULE_FROZEN_MPY +endif + SRC_LIB = $(addprefix lib/,\ utils/interrupt_char.c \ utils/stdout_helpers.c \ From a73859d5af7bc08356f69cb0ee677a0e80047148 Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Mon, 8 Jul 2019 13:07:34 +0200 Subject: [PATCH 0268/1299] py/objgenerator: Add missing #if guard for PY_GENERATOR_PEND_THROW. Without it, gen_instance_pend_throw_obj is defined but not used when MICROPY_PY_GENERATOR_PEND_THROW is set to 0. --- py/objgenerator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/py/objgenerator.c b/py/objgenerator.c index 29c7cb16d0cd8..b7186b8d0bf0d 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -297,6 +297,7 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close); +#if MICROPY_PY_GENERATOR_PEND_THROW STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); if (self->code_state.sp == self->code_state.state - 1) { @@ -307,6 +308,7 @@ STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { return prev; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_pend_throw_obj, gen_instance_pend_throw); +#endif STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gen_instance_close_obj) }, From fd49fcb229b6694d69d8f7646c7940e40b67a0cb Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 11 Jul 2019 17:32:01 +1000 Subject: [PATCH 0269/1299] stm32/gccollect: Always use MP_STATE_THREAD(stack_top) to get stack top. In a non-thread build, using &_ram_end as the top-of-stack is no longer correct because the stack is not always at the very top end of RAM. See eg 04c7cdb668cc7ee391ef5fe000f825389197f7e2 and 378659209778a1bde24e9b15793087023b02bbd9. The correct value to use is &_estack, which is the value stored in MP_STATE_THREAD(stack_top), and using the same code for both thread and non-thread builds makes the code cleaner. --- ports/stm32/gccollect.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ports/stm32/gccollect.c b/ports/stm32/gccollect.c index 5c1bf1e06d626..f5a49b7d08cba 100644 --- a/ports/stm32/gccollect.c +++ b/ports/stm32/gccollect.c @@ -48,11 +48,7 @@ void gc_collect(void) { uintptr_t sp = gc_helper_get_regs_and_sp(regs); // trace the stack, including the registers (since they live on the stack in this function) - #if MICROPY_PY_THREAD gc_collect_root((void**)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); - #else - gc_collect_root((void**)sp, ((uint32_t)&_ram_end - sp) / sizeof(uint32_t)); - #endif // trace root pointers from any threads #if MICROPY_PY_THREAD From d6e3038a080adb4024cec9bad89b4883487e12c0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 12 Jul 2019 12:57:37 +1000 Subject: [PATCH 0270/1299] ACKNOWLEDGEMENTS: Remove entry as requested by backer. --- ACKNOWLEDGEMENTS | 1 - 1 file changed, 1 deletion(-) diff --git a/ACKNOWLEDGEMENTS b/ACKNOWLEDGEMENTS index 65f731b1fffed..41ed6bf24b5a0 100644 --- a/ACKNOWLEDGEMENTS +++ b/ACKNOWLEDGEMENTS @@ -762,7 +762,6 @@ today. The names appear in order of pledging. 1642 Udine 1643 Simon Critchley 1644 Sven Haiges, Germany - 1645 Yi Qing Sim 1646 "silicium" ("silicium_one", if "silicium" is busy) 1648 Andy O'Malia, @andyomalia 1650 RedCamelApps.com From 82dc9856b06da89463e955abe2ee73a613718430 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 5 Jul 2019 15:42:33 -0500 Subject: [PATCH 0271/1299] py/asmarm: Use __builtin___clear_cache instead of __clear_cache. __clear_cache causes a compile error when using clang. Instead use __builtin___clear_cache which is available under both gcc and clang. Also replace tabs with spaces in this section of code (introduced by a previous commit). --- py/asmarm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/py/asmarm.c b/py/asmarm.c index 2a84f985ba7ee..59c661cc044a6 100644 --- a/py/asmarm.c +++ b/py/asmarm.c @@ -41,9 +41,9 @@ void asm_arm_end_pass(asm_arm_t *as) { if (as->base.pass == MP_ASM_PASS_EMIT) { #if defined(__linux__) && defined(__GNUC__) - char *start = mp_asm_base_get_code(&as->base); - char *end = start + mp_asm_base_get_code_size(&as->base); - __clear_cache(start, end); + char *start = mp_asm_base_get_code(&as->base); + char *end = start + mp_asm_base_get_code_size(&as->base); + __builtin___clear_cache(start, end); #elif defined(__arm__) // flush I- and D-cache asm volatile( From 154062d9cb1eeb1b5f1fafa25959df16bd0b0b78 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Sun, 7 Jul 2019 02:48:01 +0200 Subject: [PATCH 0272/1299] py/makeqstrdata.py: Allow using \r\n as a qstr if a port requires it. --- py/makeqstrdata.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 060ebb7fd7247..163b7fce751cc 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -279,9 +279,11 @@ def parse_input_headers(infiles): # get the qstr value qstr = match.group(1) - # special case to specify control characters + # special cases to specify control characters if qstr == '\\n': qstr = '\n' + elif qstr == '\\r\\n': + qstr = '\r\n' # work out the corresponding qstr name ident = qstr_escape(qstr) From f302f784e96f0b7daa019b282bdf66c1792eec34 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 16 Jul 2019 14:39:21 +1000 Subject: [PATCH 0273/1299] stm32/usb: Add config options to disable USB MSC and/or HID. The new configurations MICROPY_HW_USB_MSC and MICROPY_HW_USB_HID can be used by a board to enabled or disable MSC and/or HID. They are both enabled by default. --- ports/stm32/main.c | 9 ++- ports/stm32/modpyb.c | 4 +- ports/stm32/mpconfigboard_common.h | 8 +- ports/stm32/usb.c | 33 +++++++- ports/stm32/usbd_hid_interface.c | 4 + ports/stm32/usbd_msc_interface.c | 4 + .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 6 ++ .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 81 +++++++++++++++++-- ports/stm32/usbdev/class/src/usbd_msc_bot.c | 4 + ports/stm32/usbdev/class/src/usbd_msc_scsi.c | 4 +- 10 files changed, 145 insertions(+), 12 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index c05781432056f..14ea4e644bd2f 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -658,7 +658,14 @@ void stm32_main(uint32_t reset_mode) { #if MICROPY_HW_ENABLE_USB // init USB device to default setting if it was not already configured if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) { - pyb_usb_dev_init(pyb_usb_dev_detect(), USBD_VID, USBD_PID_CDC_MSC, USBD_MODE_CDC_MSC, 0, NULL, NULL); + #if MICROPY_HW_USB_MSC + const uint16_t pid = USBD_PID_CDC_MSC; + const uint8_t mode = USBD_MODE_CDC_MSC; + #else + const uint16_t pid = USBD_PID_CDC; + const uint8_t mode = USBD_MODE_CDC; + #endif + pyb_usb_dev_init(pyb_usb_dev_detect(), USBD_VID, pid, mode, 0, NULL, NULL); } #endif diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index c3e60caebb15b..139defc53bde3 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -161,10 +161,12 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { #if MICROPY_HW_ENABLE_USB { MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) }, + #if MICROPY_HW_USB_HID { MP_ROM_QSTR(MP_QSTR_hid_mouse), MP_ROM_PTR(&pyb_usb_hid_mouse_obj) }, { MP_ROM_QSTR(MP_QSTR_hid_keyboard), MP_ROM_PTR(&pyb_usb_hid_keyboard_obj) }, - { MP_ROM_QSTR(MP_QSTR_USB_VCP), MP_ROM_PTR(&pyb_usb_vcp_type) }, { MP_ROM_QSTR(MP_QSTR_USB_HID), MP_ROM_PTR(&pyb_usb_hid_type) }, + #endif + { MP_ROM_QSTR(MP_QSTR_USB_VCP), MP_ROM_PTR(&pyb_usb_vcp_type) }, #if MICROPY_PY_PYB_LEGACY // these 2 are deprecated; use USB_VCP.isconnected and USB_HID.send instead { MP_ROM_QSTR(MP_QSTR_have_cdc), MP_ROM_PTR(&pyb_have_cdc_obj) }, diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 94a86ca92a4ae..63d4238020d9a 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -273,10 +273,16 @@ #define MICROPY_HW_MAX_CAN (1) #endif -// Configure maximum number of CDC VCP interfaces +// Configure maximum number of CDC VCP interfaces, and whether MSC/HID are supported #ifndef MICROPY_HW_USB_CDC_NUM #define MICROPY_HW_USB_CDC_NUM (1) #endif +#ifndef MICROPY_HW_USB_MSC +#define MICROPY_HW_USB_MSC (MICROPY_HW_ENABLE_USB) +#endif +#ifndef MICROPY_HW_USB_HID +#define MICROPY_HW_USB_HID (MICROPY_HW_ENABLE_USB) +#endif // Pin definition header file #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h" diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 51e6e7a39249a..2d1f6084fe044 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -67,12 +67,15 @@ typedef struct _usb_device_t { USBD_HandleTypeDef hUSBDDevice; usbd_cdc_msc_hid_state_t usbd_cdc_msc_hid_state; usbd_cdc_itf_t usbd_cdc_itf[MICROPY_HW_USB_CDC_NUM]; + #if MICROPY_HW_USB_HID usbd_hid_itf_t usbd_hid_itf; + #endif } usb_device_t; usb_device_t usb_device = {0}; pyb_usb_storage_medium_t pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_NONE; +#if MICROPY_HW_USB_HID // predefined hid mouse data STATIC const mp_obj_str_t pyb_usb_hid_mouse_desc_obj = { {&mp_type_bytes}, @@ -110,6 +113,7 @@ const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = { MP_ROM_PTR(&pyb_usb_hid_keyboard_desc_obj), }, }; +#endif void pyb_usb_init0(void) { for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { @@ -160,7 +164,9 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { usb_dev->usbd_cdc_msc_hid_state.cdc[i] = &usb_dev->usbd_cdc_itf[i].base; } + #if MICROPY_HW_USB_HID usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf.base; + #endif usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state; // configure the VID, PID and the USBD mode (interfaces it will expose) @@ -170,6 +176,7 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size return false; } + #if MICROPY_HW_USB_MSC // Configure the MSC interface const void *msc_unit_default[1]; if (msc_n == 0) { @@ -188,6 +195,7 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size } usbd_msc_init_lu(msc_n, msc_unit); USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops); + #endif // start the USB device USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0); @@ -255,14 +263,29 @@ usbd_cdc_itf_t *usb_vcp_get(int idx) { */ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_port, ARG_vid, ARG_pid, ARG_msc, ARG_hid, ARG_high_speed }; + enum { + ARG_mode, ARG_port, ARG_vid, ARG_pid, + #if MICROPY_HW_USB_MSC + ARG_msc, + #endif + #if MICROPY_HW_USB_HID + ARG_hid, + #endif + #if USBD_SUPPORT_HS_MODE + ARG_high_speed + #endif + }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_vid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = USBD_VID} }, { MP_QSTR_pid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + #if MICROPY_HW_USB_MSC { MP_QSTR_msc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_empty_tuple_obj)} }, + #endif + #if MICROPY_HW_USB_HID { MP_QSTR_hid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&pyb_usb_hid_mouse_obj)} }, + #endif #if USBD_SUPPORT_HS_MODE { MP_QSTR_high_speed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, #endif @@ -381,6 +404,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // Get MSC logical units size_t msc_n = 0; const void *msc_unit[USBD_MSC_MAX_LUN]; + #if MICROPY_HW_USB_MSC if (mode & USBD_MODE_IFACE_MSC) { mp_obj_t *items; mp_obj_get_array(args[ARG_msc].u_obj, &msc_n, &items); @@ -403,9 +427,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * } } } + #endif // get hid info if user selected such a mode USBD_HID_ModeInfoTypeDef hid_info; + #if MICROPY_HW_USB_HID if (mode & USBD_MODE_IFACE_HID) { mp_obj_t *items; mp_obj_get_array_fixed_n(args[ARG_hid].u_obj, 5, &items); @@ -421,6 +447,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // need to keep a copy of this so report_desc does not get GC'd MP_STATE_PORT(pyb_hid_report_desc) = items[4]; } + #endif #if USBD_SUPPORT_HS_MODE if (args[ARG_high_speed].u_bool) { @@ -713,6 +740,8 @@ const mp_obj_type_t pyb_usb_vcp_type = { /******************************************************************************/ // MicroPython bindings for USB HID +#if MICROPY_HW_USB_HID + typedef struct _pyb_usb_hid_obj_t { mp_obj_base_t base; usb_device_t *usb_dev; @@ -841,6 +870,8 @@ const mp_obj_type_t pyb_usb_hid_type = { .locals_dict = (mp_obj_dict_t*)&pyb_usb_hid_locals_dict, }; +#endif // MICROPY_HW_USB_HID + /******************************************************************************/ // code for experimental USB OTG support diff --git a/ports/stm32/usbd_hid_interface.c b/ports/stm32/usbd_hid_interface.c index 3ffc0b425ddbc..033d83ea64843 100644 --- a/ports/stm32/usbd_hid_interface.c +++ b/ports/stm32/usbd_hid_interface.c @@ -42,6 +42,8 @@ #include "irq.h" #include "usb.h" +#if MICROPY_HW_USB_HID + uint8_t *usbd_hid_init(usbd_hid_state_t *hid_in) { usbd_hid_itf_t *hid = (usbd_hid_itf_t*)hid_in; @@ -107,3 +109,5 @@ int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout) // Success, return number of bytes read return read_len; } + +#endif // MICROPY_HW_USB_HID diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c index aa2b381a09ee7..7f563004b896e 100644 --- a/ports/stm32/usbd_msc_interface.c +++ b/ports/stm32/usbd_msc_interface.c @@ -33,6 +33,8 @@ #include "storage.h" #include "sdcard.h" +#if MICROPY_HW_USB_MSC + // This flag is needed to support removal of the medium, so that the USB drive // can be unmounted and won't be remounted automatically. #define FLAGS_STARTED (0x01) @@ -342,3 +344,5 @@ const USBD_StorageTypeDef usbd_msc_fops = { usbd_msc_Write, usbd_msc_GetMaxLun, }; + +#endif // MICROPY_HW_USB_MSC diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index c41908d25b13f..a01e75bed5e21 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -120,7 +120,9 @@ typedef struct _usbd_cdc_msc_hid_state_t { uint8_t usbd_mode; uint8_t usbd_config_desc_size; + #if MICROPY_HW_USB_MSC USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData; + #endif // RAM to hold the current descriptors, which we configure on the fly __ALIGN_BEGIN uint8_t usbd_device_desc[USB_LEN_DEV_DESC] __ALIGN_END; @@ -128,7 +130,9 @@ typedef struct _usbd_cdc_msc_hid_state_t { __ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END; usbd_cdc_state_t *cdc[MICROPY_HW_USB_CDC_NUM]; + #if MICROPY_HW_USB_HID usbd_hid_state_t *hid; + #endif } usbd_cdc_msc_hid_state_t; extern const uint8_t USBD_MSC_Mode_Sense6_Data[4]; @@ -176,9 +180,11 @@ uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd); uint8_t USBD_CDC_ReceivePacket(usbd_cdc_state_t *cdc, uint8_t *buf); uint8_t USBD_CDC_TransmitPacket(usbd_cdc_state_t *cdc, size_t len, const uint8_t *buf); +#if MICROPY_HW_USB_MSC static inline void USBD_MSC_RegisterStorage(usbd_cdc_msc_hid_state_t *usbd, USBD_StorageTypeDef *fops) { usbd->MSC_BOT_ClassData.bdev_ops = fops; } +#endif uint8_t USBD_HID_ReceivePacket(usbd_hid_state_t *usbd, uint8_t *buf); int USBD_HID_CanSendReport(usbd_hid_state_t *usbd); diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 627fb054c0f84..32ce4ca8755ea 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -148,6 +148,7 @@ static const uint8_t head_desc_data[HEAD_DESC_SIZE] = { CONFIG_DESC_MAXPOWER, // bMaxPower }; +#if MICROPY_HW_USB_MSC // USB MSC partial configuration descriptor static const uint8_t msc_class_desc_data[MSC_CLASS_DESC_SIZE] = { //========================================================================== @@ -183,6 +184,7 @@ static const uint8_t msc_class_desc_data[MSC_CLASS_DESC_SIZE] = { HIBYTE(MSC_FS_MAX_PACKET), 0x00, // bInterval: ignore for Bulk transfer }; +#endif // USB CDC partial configuration descriptor static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { @@ -276,6 +278,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { 0x00, // bInterval: ignore for Bulk transfer }; +#if MICROPY_HW_USB_HID // USB HID partial configuration descriptor static const uint8_t hid_class_desc_data[HID_CLASS_DESC_SIZE] = { //========================================================================== @@ -399,6 +402,7 @@ __ALIGN_BEGIN const uint8_t USBD_HID_KEYBOARD_ReportDesc[USBD_HID_KEYBOARD_REPOR 0x81, 0x00, // Input (Data, Array), ;Key arrays (6 bytes) 0xC0 // End Collection }; +#endif static void make_head_desc(uint8_t *dest, uint16_t len, uint8_t num_itf) { memcpy(dest, head_desc_data, sizeof(head_desc_data)); @@ -407,10 +411,12 @@ static void make_head_desc(uint8_t *dest, uint16_t len, uint8_t num_itf) { dest[4] = num_itf; // bNumInterfaces } +#if MICROPY_HW_USB_MSC static size_t make_msc_desc(uint8_t *dest) { memcpy(dest, msc_class_desc_data, sizeof(msc_class_desc_data)); return sizeof(msc_class_desc_data); } +#endif static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) { if (need_iad) { @@ -441,6 +447,7 @@ static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, u } #endif +#if MICROPY_HW_USB_HID static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info) { memcpy(dest, hid_class_desc_data, sizeof(hid_class_desc_data)); dest[HID_DESC_OFFSET_SUBCLASS] = hid_info->subclass; @@ -454,6 +461,7 @@ static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info) { dest[HID_DESC_OFFSET_POLLING_INTERVAL_OUT] = hid_info->polling_interval; return sizeof(hid_class_desc_data); } +#endif // return the saved usb mode uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd) { @@ -469,6 +477,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode uint8_t *d = usbd->usbd_config_desc; uint8_t num_itf = 0; switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { + #if MICROPY_HW_USB_MSC case USBD_MODE_MSC: n += make_msc_desc(d + n); num_itf = 1; @@ -480,6 +489,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; num_itf = 3; break; + #endif #if MICROPY_HW_USB_CDC_NUM >= 2 case USBD_MODE_CDC2: { @@ -491,6 +501,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode break; } + #if MICROPY_HW_USB_MSC case USBD_MODE_CDC2_MSC: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); @@ -501,6 +512,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode break; } #endif + #endif #if MICROPY_HW_USB_CDC_NUM >= 3 case USBD_MODE_CDC3: { @@ -514,6 +526,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode break; } + #if MICROPY_HW_USB_MSC case USBD_MODE_CDC3_MSC: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); @@ -526,7 +539,9 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode break; } #endif + #endif + #if MICROPY_HW_USB_HID case USBD_MODE_CDC_HID: usbd->hid->desc = d + n; n += make_hid_desc(d + n, hid_info); @@ -538,6 +553,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode usbd->hid->report_desc = hid_info->report_desc; num_itf = 3; break; + #endif case USBD_MODE_CDC: n += make_cdc_desc(d + n, 0, CDC_IFACE_NUM_ALONE); @@ -609,6 +625,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { } } + #if MICROPY_HW_USB_MSC if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component @@ -629,7 +646,9 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { // Init the BOT layer MSC_BOT_Init(pdev); } + #endif + #if MICROPY_HW_USB_HID if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component @@ -656,6 +675,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { usbd->hid->state = HID_IDLE; } + #endif return 0; } @@ -676,6 +696,7 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) } } + #if MICROPY_HW_USB_MSC if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component @@ -686,7 +707,9 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) // DeInit the BOT layer MSC_BOT_DeInit(pdev); } + #endif + #if MICROPY_HW_USB_HID if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component @@ -694,6 +717,7 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) USBD_LL_CloseEP(pdev, usbd->hid->in_ep); USBD_LL_CloseEP(pdev, usbd->hid->out_ep); } + #endif return 0; } @@ -725,11 +749,17 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) { case USB_REQ_RECIPIENT_INTERFACE: { uint16_t iface = req->wIndex; + #if MICROPY_HW_USB_MSC if ((mode & USBD_MODE_IFACE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { recipient = USBD_MODE_MSC; - } else if ((mode & USBD_MODE_IFACE_HID) && iface == usbd->hid->iface_num) { + } else + #endif + #if MICROPY_HW_USB_HID + if ((mode & USBD_MODE_IFACE_HID) && iface == usbd->hid->iface_num) { recipient = USBD_MODE_HID; - } else { + } else + #endif + { for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if ((mode & USBD_MODE_IFACE_CDC(i)) && iface == usbd->cdc[i]->iface_num) { recipient = USBD_MODE_CDC; @@ -742,11 +772,17 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp } case USB_REQ_RECIPIENT_ENDPOINT: { uint8_t ep = req->wIndex & 0x7f; + #if MICROPY_HW_USB_MSC if ((mode & USBD_MODE_IFACE_MSC) && ep == MSC_OUT_EP) { recipient = USBD_MODE_MSC; - } else if ((mode & USBD_MODE_IFACE_HID) && ep == usbd->hid->out_ep) { + } else + #endif + #if MICROPY_HW_USB_HID + if ((mode & USBD_MODE_IFACE_HID) && ep == usbd->hid->out_ep) { recipient = USBD_MODE_HID; - } else { + } else + #endif + { for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { if ((mode & USBD_MODE_IFACE_CDC(i)) && (ep == CDC_OUT_EP(i) || ep == (CDC_CMD_EP(i) & 0x7f))) { recipient = USBD_MODE_CDC; @@ -786,7 +822,9 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp // Transfer the command to the interface layer return usbd_cdc_control(cdc, req->bRequest, NULL, req->wValue); } - } else if (recipient == USBD_MODE_MSC) { + } + #if MICROPY_HW_USB_MSC + if (recipient == USBD_MODE_MSC) { switch (req->bRequest) { case BOT_GET_MAX_LUN: if ((req->wValue == 0) && (req->wLength == 1) && ((req->bmRequest & 0x80) == 0x80)) { @@ -811,7 +849,10 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp USBD_CtlError(pdev, req); return USBD_FAIL; } - } else if (recipient == USBD_MODE_HID) { + } + #endif + #if MICROPY_HW_USB_HID + if (recipient == USBD_MODE_HID) { switch (req->bRequest) { case HID_REQ_SET_PROTOCOL: usbd->hid->ctl_protocol = (uint8_t)(req->wValue); @@ -834,9 +875,11 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp return USBD_FAIL; } } + #endif break; case USB_REQ_TYPE_STANDARD: + #if MICROPY_HW_USB_MSC if (recipient == USBD_MODE_MSC) { switch (req->bRequest) { case USB_REQ_GET_INTERFACE : @@ -864,7 +907,10 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex); break; } - } else if (recipient == USBD_MODE_HID) { + } + #endif + #if MICROPY_HW_USB_HID + if (recipient == USBD_MODE_HID) { switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: { uint16_t len = 0; @@ -890,6 +936,7 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp break; } } + #endif break; } return USBD_OK; @@ -922,17 +969,21 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) } } + #if MICROPY_HW_USB_MSC if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { MSC_BOT_DataIn(pdev, epnum); return USBD_OK; } + #endif + #if MICROPY_HW_USB_HID if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { /* Ensure that the FIFO is empty before a new transfer, this condition could be caused by a new transfer before the end of the previous transfer */ usbd->hid->state = HID_IDLE; return USBD_OK; } + #endif return USBD_OK; } @@ -948,15 +999,19 @@ static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) } } + #if MICROPY_HW_USB_MSC if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { MSC_BOT_DataOut(pdev, epnum); return USBD_OK; } + #endif + #if MICROPY_HW_USB_HID if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) { size_t len = USBD_LL_GetRxDataSize(pdev, epnum); return usbd_hid_receive(usbd->hid, len); } + #endif return USBD_OK; } @@ -985,6 +1040,7 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * uint8_t *cdc_desc[MICROPY_HW_USB_CDC_NUM] = {0}; uint8_t *msc_desc = NULL; switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { + #if MICROPY_HW_USB_MSC case USBD_MODE_MSC: msc_desc = usbd->usbd_config_desc + MSC_TEMPLATE_MSC_DESC_OFFSET; break; @@ -993,6 +1049,7 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * cdc_desc[0] = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_MSC_DESC_OFFSET; break; + #endif #if MICROPY_HW_USB_CDC_NUM >= 2 case USBD_MODE_CDC2: @@ -1000,12 +1057,14 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * cdc_desc[1] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC2_DESC_OFFSET; break; + #if MICROPY_HW_USB_MSC case USBD_MODE_CDC2_MSC: cdc_desc[0] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET; cdc_desc[1] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET; break; #endif + #endif #if MICROPY_HW_USB_CDC_NUM >= 3 case USBD_MODE_CDC3: @@ -1014,6 +1073,7 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * cdc_desc[2] = usbd->usbd_config_desc + CDC3_TEMPLATE_CDC3_DESC_OFFSET; break; + #if MICROPY_HW_USB_MSC case USBD_MODE_CDC3_MSC: cdc_desc[0] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC_DESC_OFFSET; cdc_desc[1] = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_CDC2_DESC_OFFSET; @@ -1021,10 +1081,13 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * msc_desc = usbd->usbd_config_desc + CDC3_MSC_TEMPLATE_MSC_DESC_OFFSET; break; #endif + #endif + #if MICROPY_HW_USB_HID case USBD_MODE_CDC_HID: cdc_desc[0] = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET; break; + #endif case USBD_MODE_CDC: cdc_desc[0] = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET; @@ -1091,6 +1154,8 @@ uint8_t USBD_CDC_ReceivePacket(usbd_cdc_state_t *cdc, uint8_t *buf) { return USBD_OK; } +#if MICROPY_HW_USB_HID + // prepare OUT endpoint for reception uint8_t USBD_HID_ReceivePacket(usbd_hid_state_t *hid, uint8_t *buf) { // Suspend or Resume USB Out process @@ -1149,6 +1214,8 @@ uint8_t USBD_HID_ClearNAK(usbd_hid_state_t *hid) { return USBD_OK; } +#endif + // CDC/MSC/HID interface class callback structure const USBD_ClassTypeDef USBD_CDC_MSC_HID = { USBD_CDC_MSC_HID_Init, diff --git a/ports/stm32/usbdev/class/src/usbd_msc_bot.c b/ports/stm32/usbdev/class/src/usbd_msc_bot.c index d20f7a8dc0a17..44a74a66023d4 100644 --- a/ports/stm32/usbdev/class/src/usbd_msc_bot.c +++ b/ports/stm32/usbdev/class/src/usbd_msc_bot.c @@ -31,6 +31,8 @@ #include "usbd_cdc_msc_hid.h" #include "usbd_ioreq.h" +#if MICROPY_HW_USB_MSC + /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ */ @@ -404,4 +406,6 @@ void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum) * @} */ +#endif // MICROPY_HW_USB_MSC + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c index 26556bb48e8af..d0413b758a5d6 100644 --- a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c +++ b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c @@ -30,7 +30,7 @@ #include "usbd_msc_scsi.h" #include "usbd_cdc_msc_hid.h" - +#if MICROPY_HW_USB_MSC /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @{ @@ -789,4 +789,6 @@ static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun) * @} */ +#endif // MICROPY_HW_USB_MSC + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 788e7f50f246a7e7641217cef147ca04fd3c3ed2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 16 Jul 2019 14:41:59 +1000 Subject: [PATCH 0274/1299] stm32/usbd_cdc_interface: Make CDC TX/RX buffer sizes configurable. --- ports/stm32/usbd_cdc_interface.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/stm32/usbd_cdc_interface.h b/ports/stm32/usbd_cdc_interface.h index 780d4816e836f..a48516b1f6df6 100644 --- a/ports/stm32/usbd_cdc_interface.h +++ b/ports/stm32/usbd_cdc_interface.h @@ -31,8 +31,12 @@ ****************************************************************************** */ +#ifndef USBD_CDC_RX_DATA_SIZE #define USBD_CDC_RX_DATA_SIZE (1024) // this must be 2 or greater, and a power of 2 +#endif +#ifndef USBD_CDC_TX_DATA_SIZE #define USBD_CDC_TX_DATA_SIZE (1024) // I think this can be any value (was 2048) +#endif // Values for connect_state #define USBD_CDC_CONNECT_STATE_DISCONNECTED (0) From 4c1ad1f69160e2bb9fe683a72abba444a25d8d4f Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 16 Jul 2019 14:45:53 +1000 Subject: [PATCH 0275/1299] stm32: Add support for USB on L0 MCUs. --- ports/stm32/Makefile | 7 +++++- ports/stm32/irq.h | 11 +++++++++ ports/stm32/powerctrlboot.c | 21 ++++++++++++++++ ports/stm32/stm32_it.c | 12 +++++++++ ports/stm32/usbd_cdc_interface.c | 13 +++++++--- ports/stm32/usbd_conf.c | 42 ++++++++++++++++++++++++++++++-- 6 files changed, 100 insertions(+), 6 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 84ce01e8f951a..d2ca4122a1cf3 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -331,12 +331,17 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_uart.c \ ) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4)) +SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ + ll_usb.c \ + ) +endif + ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l4)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_sd.c \ ll_sdmmc.c \ ll_fmc.c \ - ll_usb.c \ ) endif diff --git a/ports/stm32/irq.h b/ports/stm32/irq.h index 075791357c81f..78ba46ced4651 100644 --- a/ports/stm32/irq.h +++ b/ports/stm32/irq.h @@ -79,6 +79,17 @@ static inline void restore_irq_pri(uint32_t basepri) { __set_BASEPRI(basepri); } +#else + +static inline uint32_t raise_irq_pri(uint32_t pri) { + return disable_irq(); +} + +// "state" should be the value returned from raise_irq_pri +static inline void restore_irq_pri(uint32_t state) { + enable_irq(state); +} + #endif MP_DECLARE_CONST_FUN_OBJ_0(pyb_wfi_obj); diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 527118ba88f1a..e320cc4db159d 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -98,6 +98,27 @@ void SystemClock_Config(void) { HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + + #if MICROPY_HW_ENABLE_RNG || MICROPY_HW_ENABLE_USB + // Enable the 48MHz internal oscillator + RCC->CRRCR |= RCC_CRRCR_HSI48ON; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; + SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48; + while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) { + // Wait for HSI48 to be ready + } + + // Select RC48 as HSI48 for USB and RNG + RCC->CCIPR |= RCC_CCIPR_HSI48SEL; + + #if MICROPY_HW_ENABLE_USB + // Synchronise HSI48 with 1kHz USB SoF + __HAL_RCC_CRS_CLK_ENABLE(); + CRS->CR = 0x20 << CRS_CR_TRIM_Pos; + CRS->CFGR = 2 << CRS_CFGR_SYNCSRC_Pos | 0x22 << CRS_CFGR_FELIM_Pos + | __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000) << CRS_CFGR_RELOAD_Pos; + #endif + #endif } #endif diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index fd3aea6c1c6ba..1e2712b05fbcc 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -298,6 +298,16 @@ void DebugMon_Handler(void) { /* file (startup_stm32f4xx.s). */ /******************************************************************************/ +#if defined(STM32L0) + +#if MICROPY_HW_USB_FS +void USB_IRQHandler(void) { + HAL_PCD_IRQHandler(&pcd_fs_handle); +} +#endif + +#else + /** * @brief This function handles USB-On-The-Go FS global interrupt request. * @param None @@ -405,6 +415,8 @@ void OTG_HS_WKUP_IRQHandler(void) { } #endif +#endif // !defined(STM32L0) + /** * @brief This function handles PPP interrupt request. * @param None diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index 49f0deec71242..b27ea51d87f50 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -140,11 +140,14 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, ui if (length & 1) { // The actual connection state is delayed to give the host a chance to // configure its serial port (in most cases to disable local echo) - PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING; usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs - USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM; + #if defined(STM32L0) + USB->CNTR |= USB_CNTR_SOFM; + #else + PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData; + hpcd->Instance->GINTMSK |= USB_OTG_GINTMSK_SOFM; + #endif } else { cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED; } @@ -216,7 +219,11 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { --usbd_cdc_connect_tx_timer; } else { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; + #if defined(STM32L0) + USB->CNTR &= ~USB_CNTR_SOFM; + #else hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; + #endif for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc[i]; if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index ed99700e9994f..8e62a9cc8c800 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -44,6 +44,11 @@ PCD_HandleTypeDef pcd_fs_handle; PCD_HandleTypeDef pcd_hs_handle; #endif +#if defined(STM32L0) +// The STM32L0xx has a single USB device-only instance +#define USB_OTG_FS USB +#endif + /******************************************************************************* PCD BSP Routines *******************************************************************************/ @@ -57,6 +62,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { if (hpcd->Instance == USB_OTG_FS) { #if defined(STM32H7) const uint32_t otg_alt = GPIO_AF10_OTG1_FS; + #elif defined(STM32L0) + const uint32_t otg_alt = GPIO_AF0_USB; #else const uint32_t otg_alt = GPIO_AF10_OTG_FS; #endif @@ -83,7 +90,11 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #endif // Enable USB FS Clocks + #if defined(STM32L0) + __HAL_RCC_USB_CLK_ENABLE(); + #else __USB_OTG_FS_CLK_ENABLE(); + #endif #if defined(STM32L4) // Enable VDDUSB @@ -97,8 +108,13 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #endif // Configure and enable USB FS interrupt + #if defined(STM32L0) + NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS); + HAL_NVIC_EnableIRQ(USB_IRQn); + #else NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + #endif } #if MICROPY_HW_USB_HS else if (hpcd->Instance == USB_OTG_HS) { @@ -174,6 +190,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { * @retval None */ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { + #if defined(STM32L0) + __HAL_RCC_USB_CLK_DISABLE(); + #else + if (hpcd->Instance == USB_OTG_FS) { /* Disable USB FS Clocks */ __USB_OTG_FS_CLK_DISABLE(); @@ -186,6 +206,8 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { __SYSCFG_CLK_DISABLE(); } #endif + + #endif } /******************************************************************************* @@ -339,9 +361,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { #else pcd_fs_handle.Init.dev_endpoints = 4; #endif - pcd_fs_handle.Init.use_dedicated_ep1 = 0; pcd_fs_handle.Init.ep0_mps = 0x40; - pcd_fs_handle.Init.dma_enable = 0; pcd_fs_handle.Init.low_power_enable = 0; pcd_fs_handle.Init.phy_itface = PCD_PHY_EMBEDDED; pcd_fs_handle.Init.Sof_enable = 0; @@ -350,11 +370,15 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { pcd_fs_handle.Init.lpm_enable = DISABLE; pcd_fs_handle.Init.battery_charging_enable = DISABLE; #endif + #if !defined(STM32L0) + pcd_fs_handle.Init.use_dedicated_ep1 = 0; + pcd_fs_handle.Init.dma_enable = 0; #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN) pcd_fs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0 #else pcd_fs_handle.Init.vbus_sensing_enable = 1; #endif + #endif // Link The driver to the stack pcd_fs_handle.pData = pdev; @@ -363,6 +387,18 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { // Initialize LL Driver HAL_PCD_Init(&pcd_fs_handle); + #if defined(STM32L0) + // We have 512 16-bit words it total to use here (when using PCD_SNG_BUF) + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0 + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0 + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x01, PCD_SNG_BUF, 192); // MSC / HID + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x81, PCD_SNG_BUF, 256); // MSC / HID + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x02, PCD_SNG_BUF, 320); // unused + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x82, PCD_SNG_BUF, 320); // CDC CMD + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x03, PCD_SNG_BUF, 384); // CDC DATA + HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x83, PCD_SNG_BUF, 448); // CDC DATA + #else + // We have 320 32-bit words in total to use here #if MICROPY_HW_USB_CDC_NUM == 2 HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128); @@ -379,6 +415,8 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 32); // CDC CMD HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 64); // CDC DATA #endif + + #endif } #endif #if MICROPY_HW_USB_HS From 4096fa397b195a6ef82e48a74deaa8dd026d8a41 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 16 Jul 2019 14:46:31 +1000 Subject: [PATCH 0276/1299] stm32/powerctrlboot: Increase SYSCLK to 32MHz for L0 MCUs. --- ports/stm32/powerctrlboot.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index e320cc4db159d..de7c9d88a734a 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -82,11 +82,21 @@ void SystemClock_Config(void) { // Enable power control peripheral __HAL_RCC_PWR_CLK_ENABLE(); - // Use the 16MHz internal oscillator + // Set flash latency to 1 because SYSCLK > 16MHz + FLASH->ACR |= FLASH_ACR_LATENCY; + + // Enable the 16MHz internal oscillator RCC->CR |= RCC_CR_HSION; while (!(RCC->CR & RCC_CR_HSIRDY)) { } - const uint32_t sysclk_src = 1; + + // Use HSI16 and the PLL to get a 32MHz SYSCLK + RCC->CFGR = 1 << RCC_CFGR_PLLDIV_Pos | 1 << RCC_CFGR_PLLMUL_Pos; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) { + // Wait for PLL to lock + } + const uint32_t sysclk_src = 3; // Select SYSCLK source RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; From 102d9911e988959a7ef0e5f8123c41b4aca5c144 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 16 Jul 2019 14:47:12 +1000 Subject: [PATCH 0277/1299] stm32/mphalport: Fix GPIO clock enable for L0 MCUs. --- ports/stm32/mphalport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index c5786e7409314..fe7772cf68b31 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -121,7 +121,7 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #define AHBxENR_GPIOAEN_Pos RCC_AHB4ENR_GPIOAEN_Pos #elif defined(STM32L0) #define AHBxENR IOPENR - #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_GPIOAEN + #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_IOPAEN_Pos #elif defined(STM32L4) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos From 64aebca1553bea62b4266c0194838a5a7df0e91f Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 16 Jul 2019 14:47:32 +1000 Subject: [PATCH 0278/1299] stm32/Makefile: Allow a board to disable float support. By using "MICROPY_FLOAT_IMPL = none" in its mpconfigboard.mk file. --- ports/stm32/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index d2ca4122a1cf3..f74180d39714f 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -91,9 +91,13 @@ CFLAGS += -DMICROPY_HW_VTOR=$(TEXT0_ADDR) ifeq ($(MICROPY_FLOAT_IMPL),double) CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE else +ifeq ($(MICROPY_FLOAT_IMPL),none) +CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE +else CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT CFLAGS += -fsingle-precision-constant -Wdouble-promotion endif +endif LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref LDFLAGS += --defsym=_estack_reserve=8 From baea43bba79152319e66668afa55b64a9e13c1a5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 16 Jul 2019 14:48:08 +1000 Subject: [PATCH 0279/1299] stm32/boards/B_L072Z_LRWAN1: Enable USB VCP support. --- ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h | 8 ++++++++ ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk | 1 + 2 files changed, 9 insertions(+) diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h index da219abd30d38..7a80f26356520 100644 --- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h @@ -19,6 +19,7 @@ #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_ADC (0) +#define MICROPY_HW_ENABLE_USB (1) #define MICROPY_HW_HAS_SWITCH (1) // UART config @@ -58,3 +59,10 @@ #define MICROPY_HW_LED4 (pin_B7) // Red #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// USB config (need to bridge SB15/SB16) +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_MSC (0) +#define MICROPY_HW_USB_HID (0) +#define USBD_CDC_RX_DATA_SIZE (256) +#define USBD_CDC_TX_DATA_SIZE (256) diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk index a39a2bd47b378..084cf4d309e97 100644 --- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk @@ -1,5 +1,6 @@ MCU_SERIES = l0 CMSIS_MCU = STM32L072xx +MICROPY_FLOAT_IMPL = none AF_FILE = boards/stm32l072_af.csv LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld From a67d9155e61d41898888da3a6884e73c3a270781 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 8 Jul 2019 17:18:47 +1000 Subject: [PATCH 0280/1299] travis: Switch unix stackless build to use clang. To test a different compiler, other than gcc. --- .travis.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0088fbe90d1b8..1229e6e689c57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -106,13 +106,14 @@ jobs: # unix stackless - stage: test - env: NAME="unix stackless port build and tests" + env: NAME="unix stackless port build and tests with clang" + install: + - sudo apt-get install clang script: - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - - make ${MAKEOPTS} -C mpy-cross - - make ${MAKEOPTS} -C ports/unix deplibs - - make ${MAKEOPTS} -C ports/unix CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1" - - make ${MAKEOPTS} -C ports/unix test + - make ${MAKEOPTS} -C mpy-cross CC=clang + - make ${MAKEOPTS} -C ports/unix CC=clang CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1" + - make ${MAKEOPTS} -C ports/unix CC=clang test # windows port via mingw - stage: test From 3e558300669effa93e5e4dad4c8c4ecc167766c4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 15:33:27 +1000 Subject: [PATCH 0281/1299] tests/stress/recursive_iternext.py: Increase large depth to 5000. So it fails correctly on Linux with clang. --- tests/stress/recursive_iternext.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stress/recursive_iternext.py b/tests/stress/recursive_iternext.py index edb5a843f29dc..bbc389e726237 100644 --- a/tests/stress/recursive_iternext.py +++ b/tests/stress/recursive_iternext.py @@ -14,7 +14,7 @@ try: # large stack/heap, eg unix [0] * 80000 - N = 2400 + N = 5000 except: try: # medium, eg pyboard From bc66fe9064c48268dbc88b8c3197f560351b1039 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 11 Jul 2019 11:55:31 +1000 Subject: [PATCH 0282/1299] py/scheduler: Rename sched_stack to sched_queue. Behaviour was changed from stack to queue in 8977c7eb581f5d06500edb1ea29aea5cbda04f28, and this updates variable names to match. Also updates other references (docs, error messages). --- docs/library/micropython.rst | 4 ++-- py/modmicropython.c | 2 +- py/mpstate.h | 2 +- py/scheduler.c | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst index d9f913bffdad5..2b4c1168c9b59 100644 --- a/docs/library/micropython.rst +++ b/docs/library/micropython.rst @@ -136,5 +136,5 @@ Functions :ref:`reference documentation ` under "Creation of Python objects". - There is a finite stack to hold the scheduled functions and `schedule()` - will raise a `RuntimeError` if the stack is full. + There is a finite queue to hold the scheduled functions and `schedule()` + will raise a `RuntimeError` if the queue is full. diff --git a/py/modmicropython.c b/py/modmicropython.c index 864d1a5c5bcbe..8d36697f15dd3 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -150,7 +150,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd #if MICROPY_ENABLE_SCHEDULER STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) { if (!mp_sched_schedule(function, arg)) { - mp_raise_msg(&mp_type_RuntimeError, "schedule stack full"); + mp_raise_msg(&mp_type_RuntimeError, "schedule queue full"); } return mp_const_none; } diff --git a/py/mpstate.h b/py/mpstate.h index a9c2b32d66e28..b7eb6bdeb1505 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -141,7 +141,7 @@ typedef struct _mp_state_vm_t { volatile mp_obj_t mp_pending_exception; #if MICROPY_ENABLE_SCHEDULER - mp_sched_item_t sched_stack[MICROPY_SCHEDULER_DEPTH]; + mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]; #endif // current exception being handled, for sys.exc_info() diff --git a/py/scheduler.c b/py/scheduler.c index 5edff45b6fc50..e7cbb524de7d3 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -65,7 +65,7 @@ void mp_handle_pending(void) { void mp_handle_pending_tail(mp_uint_t atomic_state) { MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; if (!mp_sched_empty()) { - mp_sched_item_t item = MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_idx)]; + mp_sched_item_t item = MP_STATE_VM(sched_queue)[MP_STATE_VM(sched_idx)]; MP_STATE_VM(sched_idx) = IDX_MASK(MP_STATE_VM(sched_idx) + 1); --MP_STATE_VM(sched_len); MICROPY_END_ATOMIC_SECTION(atomic_state); @@ -107,11 +107,11 @@ bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; } uint8_t iput = IDX_MASK(MP_STATE_VM(sched_idx) + MP_STATE_VM(sched_len)++); - MP_STATE_VM(sched_stack)[iput].func = function; - MP_STATE_VM(sched_stack)[iput].arg = arg; + MP_STATE_VM(sched_queue)[iput].func = function; + MP_STATE_VM(sched_queue)[iput].arg = arg; ret = true; } else { - // schedule stack is full + // schedule queue is full ret = false; } MICROPY_END_ATOMIC_SECTION(atomic_state); From 3b3a4749ce46febe4d19a2392e94485c0659eb98 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Tue, 16 Jul 2019 06:00:36 +0200 Subject: [PATCH 0283/1299] py/objstringio: Guard bytesio_stream_p struct w/ MICROPY_PY_IO_BYTESIO. It's static and can lead to a compilation warning/error when MICROPY_PY_IO_BYTESIO is disabled. --- py/objstringio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/py/objstringio.c b/py/objstringio.c index 89b679031250d..8f1f7611389e8 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -244,12 +244,6 @@ STATIC const mp_stream_p_t stringio_stream_p = { .is_text = true, }; -STATIC const mp_stream_p_t bytesio_stream_p = { - .read = stringio_read, - .write = stringio_write, - .ioctl = stringio_ioctl, -}; - const mp_obj_type_t mp_type_stringio = { { &mp_type_type }, .name = MP_QSTR_StringIO, @@ -262,6 +256,12 @@ const mp_obj_type_t mp_type_stringio = { }; #if MICROPY_PY_IO_BYTESIO +STATIC const mp_stream_p_t bytesio_stream_p = { + .read = stringio_read, + .write = stringio_write, + .ioctl = stringio_ioctl, +}; + const mp_obj_type_t mp_type_bytesio = { { &mp_type_type }, .name = MP_QSTR_BytesIO, From 02b2ad4fbdbfae3e06ee4d0c686be36509d53d7d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 16:19:06 +1000 Subject: [PATCH 0284/1299] stm32/boards/STM32F769DISC: Fix length of FLASH_APP section. Fixes issue #4924. --- ports/stm32/boards/STM32F769DISC/f769_qspi.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld index 9a0bd56fb34d9..5f920b417fdde 100644 --- a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld +++ b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld @@ -17,7 +17,7 @@ MEMORY { - FLASH_APP (rx) : ORIGIN = 0x08020000, LENGTH = 2016K /* sectors 1-11 3x32K 1*128K 7*256K */ + FLASH_APP (rx) : ORIGIN = 0x08020000, LENGTH = 1920K /* sectors 4-11 1*128K 7*256K */ FLASH_QSPI (rx) : ORIGIN = 0x90000000, LENGTH = 64M /* external QSPI flash in XIP mode */ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for storage cache */ RAM (xrw) : ORIGIN = 0x20020000, LENGTH = 384K /* SRAM1 = 368K, SRAM2 = 16K */ From d42392b9a78d03080d12cc17283c570c3edf8016 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 16:27:17 +1000 Subject: [PATCH 0285/1299] stm32/make-stmconst.py: Allow more variation in parens and int-suffix L. --- ports/stm32/make-stmconst.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/make-stmconst.py b/ports/stm32/make-stmconst.py index cfcc12f59e1d1..41ec9b56f4bcb 100644 --- a/ports/stm32/make-stmconst.py +++ b/ports/stm32/make-stmconst.py @@ -40,9 +40,9 @@ class Lexer: re_comment = r'(?P[A-Za-z0-9 \-/_()&]+)' re_addr_offset = r'Address offset: (?P0x[0-9A-Z]{2,3})' regexs = ( - ('#define hex', re.compile(r'#define +(?P[A-Z0-9_]+) +(?:\(\(uint32_t\))?(?P0x[0-9A-F]+)U?(?:\))?($| +/\*)')), + ('#define hex', re.compile(r'#define +(?P[A-Z0-9_]+) +\(?(\(uint32_t\))?(?P0x[0-9A-F]+)U?L?\)?($| */\*)')), ('#define X', re.compile(r'#define +(?P[A-Z0-9_]+) +(?P[A-Z0-9_]+)($| +/\*)')), - ('#define X+hex', re.compile(r'#define +(?P[A-Za-z0-9_]+) +\((?P[A-Z0-9_]+) \+ (?P0x[0-9A-F]+)U?\)($| +/\*)')), + ('#define X+hex', re.compile(r'#define +(?P[A-Za-z0-9_]+) +\(?(?P[A-Z0-9_]+) \+ (?P0x[0-9A-F]+)U?L?\)?($| +/\*)')), ('#define typedef', re.compile(r'#define +(?P[A-Z0-9_]+(ext)?) +\(\([A-Za-z0-9_]+_TypeDef \*\) (?P[A-Za-z0-9_]+)\)($| +/\*)')), ('typedef struct', re.compile(r'typedef struct$')), ('{', re.compile(r'{$')), From 59b7166d87b480517ca5905ee2239dc2cace18b9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 16:33:31 +1000 Subject: [PATCH 0286/1299] stm32: Add initial support for STM32WBxx MCUs. This new series of MCUs is similar to the L4 series with an additional Cortex-M0 coprocessor. The firmware for the wireless stack must be managed separately and MicroPython does not currently interface to it. Supported features so far include: RTC, UART, USB, internal flash filesystem. --- ports/stm32/Makefile | 5 ++-- ports/stm32/dma.c | 14 +++++++++ ports/stm32/dma.h | 2 +- ports/stm32/extint.c | 28 ++++++++++++++++-- ports/stm32/extint.h | 2 +- ports/stm32/flash.c | 8 +++--- ports/stm32/flashbdev.c | 3 +- ports/stm32/machine_uart.c | 2 +- ports/stm32/modmachine.c | 4 +-- ports/stm32/mpconfigboard_common.h | 9 ++++++ ports/stm32/mphalport.c | 2 +- ports/stm32/powerctrl.c | 13 +++++---- ports/stm32/powerctrlboot.c | 46 ++++++++++++++++++++++++++++++ ports/stm32/rtc.c | 22 +++++++++----- ports/stm32/stm32_it.c | 8 ++++++ ports/stm32/system_stm32.c | 4 +++ ports/stm32/uart.c | 8 ++++-- ports/stm32/usbd_cdc_interface.c | 4 +-- ports/stm32/usbd_conf.c | 19 ++++++++---- 19 files changed, 165 insertions(+), 38 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index f74180d39714f..e868d6de1bc75 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -79,6 +79,7 @@ CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 +CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) @@ -335,7 +336,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_uart.c \ ) -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4 wb)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ ll_usb.c \ ) @@ -361,7 +362,7 @@ endif ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c) else -ifneq ($(MCU_SERIES),$(filter $(MCU_SERIES),l0)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 h7 l4)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_can.c) endif endif diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 2c7371e010e64..8a3f743fe7157 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -34,6 +34,18 @@ #include "dma.h" #include "irq.h" +#if defined(STM32WB) + +// DMA is currently not implemented for this MCU + +void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data) { +} + +void dma_deinit(const dma_descr_t *dma_descr) { +} + +#else + #define DMA_IDLE_ENABLED() (dma_idle.enabled != 0) #define DMA_SYSTICK_LOG2 (3) #define DMA_SYSTICK_MASK ((1 << DMA_SYSTICK_LOG2) - 1) @@ -919,3 +931,5 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a } #endif + +#endif // defined(STM32WB) diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 6d07a94ed99af..5a17276a49de2 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -73,7 +73,7 @@ extern const dma_descr_t dma_I2C_2_RX; extern const dma_descr_t dma_I2C_1_TX; extern const dma_descr_t dma_I2C_1_RX; -#elif defined(STM32L4) +#elif defined(STM32L4) || defined(STM32WB) extern const dma_descr_t dma_ADC_1_RX; extern const dma_descr_t dma_ADC_2_RX; diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 9a7295995a827..836b0c5954de6 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -91,7 +91,7 @@ #define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4))) #endif -#if defined(STM32L4) +#if defined(STM32L4) || defined(STM32WB) // The L4 MCU supports 40 Events/IRQs lines of the type configurable and direct. // Here we only support configurable line types. Details, see page 330 of RM0351, Rev 1. // The USB_FS_WAKUP event is a direct type and there is no support for it. @@ -140,6 +140,7 @@ STATIC mp_obj_t pyb_extint_callback_arg[EXTI_NUM_VECTORS]; STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { #if defined(STM32F0) || defined(STM32L0) + EXTI0_1_IRQn, EXTI0_1_IRQn, EXTI2_3_IRQn, EXTI2_3_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, @@ -155,11 +156,19 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { RTC_IRQn, ADC1_COMP_IRQn, ADC1_COMP_IRQn, + #else + EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, + #if defined(STM32WB) + PVD_PVM_IRQn, + RTC_Alarm_IRQn, + TAMP_STAMP_LSECSS_IRQn, + RTC_WKUP_IRQn, + #else #if defined(STM32L4) PVD_PVM_IRQn, #else @@ -177,6 +186,8 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { TAMP_STAMP_IRQn, RTC_WKUP_IRQn, #endif + + #endif }; // Set override_callback_obj to true if you want to unconditionally set the @@ -285,7 +296,9 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_ pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI + #if !defined(STM32WB) __HAL_RCC_SYSCFG_CLK_ENABLE(); + #endif SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); @@ -320,7 +333,9 @@ void extint_set(const pin_obj_t *pin, uint32_t mode) { pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI + #if !defined(STM32WB) __HAL_RCC_SYSCFG_CLK_ENABLE(); + #endif SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); @@ -358,12 +373,16 @@ void extint_enable(uint line) { if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { #if defined(STM32H7) EXTI_D1->IMR1 |= (1 << line); + #elif defined(STM32WB) + EXTI->IMR1 |= (1 << line); #else EXTI->IMR |= (1 << line); #endif } else { #if defined(STM32H7) EXTI_D1->EMR1 |= (1 << line); + #elif defined(STM32WB) + EXTI->EMR1 |= (1 << line); #else EXTI->EMR |= (1 << line); #endif @@ -388,6 +407,9 @@ void extint_disable(uint line) { #if defined(STM32H7) EXTI_D1->IMR1 &= ~(1 << line); EXTI_D1->EMR1 &= ~(1 << line); + #elif defined(STM32WB) + EXTI->IMR1 &= ~(1 << line); + EXTI->EMR1 &= ~(1 << line); #else EXTI->IMR &= ~(1 << line); EXTI->EMR &= ~(1 << line); @@ -407,7 +429,7 @@ void extint_swint(uint line) { return; } // we need 0 to 1 transition to trigger the interrupt -#if defined(STM32L4) || defined(STM32H7) +#if defined(STM32L4) || defined(STM32H7) || defined(STM32WB) EXTI->SWIER1 &= ~(1 << line); EXTI->SWIER1 |= (1 << line); #else @@ -485,7 +507,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint); /// \classmethod regs() /// Dump the values of the EXTI registers. STATIC mp_obj_t extint_regs(void) { - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1); printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2); printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1); diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h index d275087c9e28f..907af53dc22b1 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -46,7 +46,7 @@ #if defined(STM32F0) || defined(STM32L4) #define EXTI_RTC_TIMESTAMP (19) #define EXTI_RTC_WAKEUP (20) -#elif defined(STM32H7) +#elif defined(STM32H7) || defined(STM32WB) #define EXTI_RTC_TIMESTAMP (18) #define EXTI_RTC_WAKEUP (19) #else diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index aff85f7e3798b..58cc012793b5d 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -68,7 +68,7 @@ static const flash_layout_t flash_layout[] = { { 0x08040000, 0x40000, 3 }, }; -#elif defined(STM32L0) || defined(STM32L4) +#elif defined(STM32L0) || defined(STM32L4) || defined(STM32WB) static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, @@ -122,7 +122,7 @@ static uint32_t get_page(uint32_t addr) { } #endif -#elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE) +#elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) static uint32_t get_page(uint32_t addr) { return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; @@ -175,7 +175,7 @@ void flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; - #elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE) + #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); @@ -247,7 +247,7 @@ void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) { */ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) // program the flash uint64 by uint64 for (int i = 0; i < num_word32 / 2; i++) { diff --git a/ports/stm32/flashbdev.c b/ports/stm32/flashbdev.c index 0a5f417040f9f..470f3d086061e 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -105,7 +105,8 @@ STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k #elif defined(STM32L432xx) || \ defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) || \ - defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) || \ + defined(STM32WB) // The STM32L4xx doesn't have CCRAM, so we use SRAM2 for this, although // actual location and size is defined by the linker script. diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 92343ba6d713f..5dbc133310b1f 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -489,7 +489,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar); // uart.sendbreak() STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) self->uartx->RQR = USART_RQR_SBKRQ; // write-only register #else self->uartx->CR1 |= USART_CR1_SBK; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 8d6dbf4fec49d..e45f81479bfb5 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -61,7 +61,7 @@ #define RCC_CSR_BORRSTF RCC_CSR_PORRSTF #endif -#if defined(STM32L4) +#if defined(STM32L4) || defined(STM32WB) // L4 does not have a POR, so use BOR instead #define RCC_CSR_PORRSTF RCC_CSR_BORRSTF #endif @@ -305,7 +305,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } else { // set - #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) mp_raise_NotImplementedError("machine.freq set not supported yet"); #else mp_int_t sysclk = mp_obj_get_int(args[0]); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 63d4238020d9a..121b64d038660 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -202,6 +202,15 @@ #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (6) +// Configuration for STM32WB series +#elif defined(STM32WB) + +#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE) +#define PYB_EXTI_NUM_VECTORS (20) +#define MICROPY_HW_MAX_I2C (3) +#define MICROPY_HW_MAX_TIMER (17) +#define MICROPY_HW_MAX_UART (1) + #else #error Unsupported MCU series #endif diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index fe7772cf68b31..ec4590b06bb49 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -122,7 +122,7 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #elif defined(STM32L0) #define AHBxENR IOPENR #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_IOPAEN_Pos - #elif defined(STM32L4) + #elif defined(STM32L4) || defined(STM32WB) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos #endif diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 067e4c176e518..68a8bfdaf340a 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -76,7 +76,7 @@ void powerctrl_check_enter_bootloader(void) { if ((bl_addr & 0xfff) == 0 && (RCC->RCC_SR & RCC_SR_SFTRSTF)) { // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader RCC->RCC_SR = RCC_SR_RMVF; - #if defined(STM32F0) || defined(STM32F4) || defined(STM32L4) + #if defined(STM32F0) || defined(STM32F4) || defined(STM32L4) || defined(STM32WB) __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); #endif uint32_t r0 = BL_STATE[0]; @@ -84,7 +84,7 @@ void powerctrl_check_enter_bootloader(void) { } } -#if !defined(STM32F0) && !defined(STM32L0) +#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32WB) // Assumes that PLL is used as the SYSCLK source int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) { @@ -158,7 +158,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk #endif -#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) +#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; } @@ -333,7 +333,7 @@ void powerctrl_enter_stop_mode(void) { __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif - #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) + #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif @@ -380,6 +380,9 @@ void powerctrl_enter_stop_mode(void) { #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } + #elif defined(STM32WB) + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { + } #else while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) { } @@ -450,7 +453,7 @@ void powerctrl_enter_standby_mode(void) { PWR->CR2 |= PWR_CR2_CWUPF6 | PWR_CR2_CWUPF5 | PWR_CR2_CWUPF4 | PWR_CR2_CWUPF3 | PWR_CR2_CWUPF2 | PWR_CR2_CWUPF1; #elif defined(STM32H7) // TODO - #elif defined(STM32L4) + #elif defined(STM32L4) || defined(STM32WB) // clear all wake-up flags PWR->SCR |= PWR_SCR_CWUF5 | PWR_SCR_CWUF4 | PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1; // TODO diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index de7c9d88a734a..8884f596ed009 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -131,4 +131,50 @@ void SystemClock_Config(void) { #endif } +#elif defined(STM32WB) + +void SystemClock_Config(void) { + // Enable the 32MHz external oscillator + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR & RCC_CR_HSERDY)) { + } + + // Use HSE and the PLL to get a 64MHz SYSCLK + #define PLLM (HSE_VALUE / 8000000) // VCO input is 8MHz + #define PLLN (24) // 24*8MHz = 192MHz + #define PLLQ (4) // f_Q = 48MHz + #define PLLR (3) // f_R = 64MHz + RCC->PLLCFGR = + (PLLR - 1) << RCC_PLLCFGR_PLLR_Pos | RCC_PLLCFGR_PLLREN + | (PLLQ - 1) << RCC_PLLCFGR_PLLQ_Pos | RCC_PLLCFGR_PLLQEN + | PLLN << RCC_PLLCFGR_PLLN_Pos + | (PLLM - 1) << RCC_PLLCFGR_PLLM_Pos + | 3 << RCC_PLLCFGR_PLLSRC_Pos; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) { + // Wait for PLL to lock + } + const uint32_t sysclk_src = 3; + + // Set divider for HCLK2 to 2 so f_HCLK2 = 32MHz + RCC->EXTCFGR = 8 << RCC_EXTCFGR_C2HPRE_Pos; + + // Set flash latency to 3 because SYSCLK > 54MHz + FLASH->ACR |= 3 << FLASH_ACR_LATENCY_Pos; + + // Select SYSCLK source + RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { + // Wait for SYSCLK source to change + } + + // Select PLLQ as 48MHz source for USB and RNG + RCC->CCIPR = 2 << RCC_CCIPR_CLK48SEL_Pos; + + SystemCoreClockUpdate(); + + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); +} + #endif diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index d0f444c216269..4019617ac87f5 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -31,6 +31,14 @@ #include "rtc.h" #include "irq.h" +#if defined(STM32WB) +#define RCC_CSR_LSION RCC_CSR_LSI1ON +#define RCC_FLAG_LSIRDY RCC_FLAG_LSI1RDY +#define RCC_OSCILLATORTYPE_LSI RCC_OSCILLATORTYPE_LSI1 +#define __HAL_RCC_LSI_ENABLE __HAL_RCC_LSI1_ENABLE +#define __HAL_RCC_LSI_DISABLE __HAL_RCC_LSI1_DISABLE +#endif + /// \moduleref pyb /// \class RTC - real time clock /// @@ -177,7 +185,7 @@ void rtc_init_finalise() { // fresh reset; configure RTC Calendar RTC_CalendarConfig(); - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET) { #else if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) { @@ -209,7 +217,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc /*------------------------------ LSE Configuration -------------------------*/ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) { - #if !defined(STM32H7) + #if !defined(STM32H7) && !defined(STM32WB) // Enable Power Clock __HAL_RCC_PWR_CLK_ENABLE(); #endif @@ -218,7 +226,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc HAL_PWR_EnableBkUpAccess(); uint32_t tickstart = HAL_GetTick(); - #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) //__HAL_RCC_PWR_CLK_ENABLE(); // Enable write access to Backup domain //PWR->CR1 |= PWR_CR1_DBP; @@ -298,7 +306,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) { // Exit Initialization mode hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; - #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMOUTTYPE; hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType); #elif defined(STM32F7) @@ -649,7 +657,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { RTC->WPR = 0xff; // enable external interrupts on line EXTI_RTC_WAKEUP - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) @@ -662,7 +670,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { // clear interrupt flags RTC->ISR &= ~RTC_ISR_WUTF; - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) EXTI->PR1 = 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) EXTI_D1->PR1 = 1 << EXTI_RTC_WAKEUP; @@ -682,7 +690,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { RTC->WPR = 0xff; // disable external interrupts on line EXTI_RTC_WAKEUP - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) EXTI->IMR1 &= ~(1 << EXTI_RTC_WAKEUP); #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 1e2712b05fbcc..16db92d1d7aa3 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -306,6 +306,14 @@ void USB_IRQHandler(void) { } #endif +#elif defined(STM32WB) + +#if MICROPY_HW_USB_FS +void USB_LP_IRQHandler(void) { + HAL_PCD_IRQHandler(&pcd_fs_handle); +} +#endif + #else /** diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index deb23e2f5f0c4..0792d124d6153 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -78,6 +78,8 @@ #include "py/mphal.h" #include "powerctrl.h" +#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4) + void __fatal_error(const char *msg); /** @@ -392,3 +394,5 @@ void SystemClock_Config(void) NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, TICK_INT_PRIORITY, 0)); #endif } + +#endif diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 0d46ea9473599..f577eb787fa0d 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -81,7 +81,7 @@ #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) -#elif defined(STM32L4) +#elif defined(STM32L4) || defined(STM32WB) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #if defined(USART_CR3_TCBGTIE) @@ -439,11 +439,13 @@ void uart_deinit(pyb_uart_obj_t *self) { __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); __HAL_RCC_USART1_CLK_DISABLE(); + #if defined(USART2) } else if (self->uart_id == 2) { HAL_NVIC_DisableIRQ(USART2_IRQn); __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); __HAL_RCC_USART2_CLK_DISABLE(); + #endif #if defined(USART3) } else if (self->uart_id == 3) { #if !defined(STM32F0) @@ -653,7 +655,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) int data = self->uartx->RDR & self->char_mask; self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set return data; @@ -779,7 +781,7 @@ void uart_irq_handler(mp_uint_t uart_id) { uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len; if (next_head != self->read_buf_tail) { // only read data if room in buf - #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) int data = self->uartx->RDR; // clears UART_FLAG_RXNE self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set #else diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index b27ea51d87f50..e234230196cc7 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -142,7 +142,7 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, ui // configure its serial port (in most cases to disable local echo) cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING; usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) USB->CNTR |= USB_CNTR_SOFM; #else PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData; @@ -219,7 +219,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { --usbd_cdc_connect_tx_timer; } else { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) USB->CNTR &= ~USB_CNTR_SOFM; #else hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 8e62a9cc8c800..437d96ae7877f 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -44,7 +44,7 @@ PCD_HandleTypeDef pcd_fs_handle; PCD_HandleTypeDef pcd_hs_handle; #endif -#if defined(STM32L0) +#if defined(STM32L0) || defined(STM32WB) // The STM32L0xx has a single USB device-only instance #define USB_OTG_FS USB #endif @@ -64,6 +64,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { const uint32_t otg_alt = GPIO_AF10_OTG1_FS; #elif defined(STM32L0) const uint32_t otg_alt = GPIO_AF0_USB; + #elif defined(STM32WB) + const uint32_t otg_alt = GPIO_AF10_USB; #else const uint32_t otg_alt = GPIO_AF10_OTG_FS; #endif @@ -90,7 +92,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #endif // Enable USB FS Clocks - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) __HAL_RCC_USB_CLK_ENABLE(); #else __USB_OTG_FS_CLK_ENABLE(); @@ -111,6 +113,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #if defined(STM32L0) NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_IRQn); + #elif defined(STM32WB) + NVIC_SetPriority(USB_LP_IRQn, IRQ_PRI_OTG_FS); + HAL_NVIC_EnableIRQ(USB_LP_IRQn); #else NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); @@ -190,7 +195,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { * @retval None */ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) __HAL_RCC_USB_CLK_DISABLE(); #else @@ -354,6 +359,10 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { #if MICROPY_HW_USB_FS if (pdev->id == USB_PHY_FS_ID) { + #if defined(STM32WB) + PWR->CR2 |= PWR_CR2_USV; // USB supply is valid + #endif + // Set LL Driver parameters pcd_fs_handle.Instance = USB_OTG_FS; #if MICROPY_HW_USB_CDC_NUM == 2 @@ -370,7 +379,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { pcd_fs_handle.Init.lpm_enable = DISABLE; pcd_fs_handle.Init.battery_charging_enable = DISABLE; #endif - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32WB) pcd_fs_handle.Init.use_dedicated_ep1 = 0; pcd_fs_handle.Init.dma_enable = 0; #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN) @@ -387,7 +396,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { // Initialize LL Driver HAL_PCD_Init(&pcd_fs_handle); - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) // We have 512 16-bit words it total to use here (when using PCD_SNG_BUF) HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0 HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0 From 9849567a065a1abee1dc406856ce4b50d1f678e5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 16:40:02 +1000 Subject: [PATCH 0287/1299] stm32/boards: Add MCU support files for STM32WB55. --- ports/stm32/boards/stm32wb55_af.csv | 74 +++++++++++++++++++ ports/stm32/boards/stm32wb55xg.ld | 33 +++++++++ ports/stm32/boards/stm32wbxx_hal_conf_base.h | 78 ++++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 ports/stm32/boards/stm32wb55_af.csv create mode 100644 ports/stm32/boards/stm32wb55xg.ld create mode 100644 ports/stm32/boards/stm32wbxx_hal_conf_base.h diff --git a/ports/stm32/boards/stm32wb55_af.csv b/ports/stm32/boards/stm32wb55_af.csv new file mode 100644 index 0000000000000..6e4ddd9608250 --- /dev/null +++ b/ports/stm32/boards/stm32wb55_af.csv @@ -0,0 +1,74 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, +,,SYS_AF,TIM1/TIM2/LPTIM1,TIM1/TIM2,SPI2/SAI1/TIM1,I2C1/I2C3,SPI1/SPI2,RF,USART1,LPUART1,TSC,USB/QUADSPI,LCD,COMP1/COMP2/TIM1,SAI1,TIM2/TIM16/TIM17/LPTIM2,EVENTOUT,ADC +PortA,PA0,,TIM2_CH1,,,,,,,,,,,COMP1_OUT,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC123_IN0 +PortA,PA1,,TIM2_CH2,,,I2C1_SMBA,SPI1_SCK,,,,,,LCD_SEG0,,,,EVENTOUT,ADC123_IN1 +PortA,PA2,LSCO,TIM2_CH3,,,,,,,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG1,COMP2_OUT,,,EVENTOUT,ADC123_IN2 +PortA,PA3,,TIM2_CH4,,SAI1_PDM_CK1,,,,,LPUART1_RX,,QUADSPI_CLK,LCD_SEG2,,SAI1_MCLK_A,,EVENTOUT,ADC123_IN3 +PortA,PA4,,,,,,SPI1_NSS,,,,,,LCD_SEG5,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC12_IN4 +PortA,PA5,,TIM2_CH1,TIM2_ETR,,,SPI1_SCK,,,,,,,,SAI1_SD_B,LPTIM2_ETR,EVENTOUT,ADC12_IN5 +PortA,PA6,,TIM1_BKIN,,,,SPI1_MISO,,,LPUART1_CTS,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN,,TIM16_CH1,EVENTOUT,ADC12_IN6 +PortA,PA7,,TIM1_CH1N,,,I2C3_SCL,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,COMP2_OUT,,TIM17_CH1,EVENTOUT,ADC12_IN7 +PortA,PA8,MCO,TIM1_CH1,,SAI1_PDM_CK2,,,,USART1_CK,,,,LCD_COM0,,SAI1_SCK_A,LPTIM2_OUT,EVENTOUT, +PortA,PA9,,TIM1_CH2,,SAI1_PDM_DI2,I2C1_SCL,SPI2_SCK,,USART1_TX,,,,LCD_COM1,,SAI1_FS_A,,EVENTOUT, +PortA,PA10,,TIM1_CH3,,SAI1_PDM_DI1,I2C1_SDA,,,USART1_RX,,,USB_CRS_SYNC,LCD_COM2,,SAI1_SD_A,TIM17_BKIN,EVENTOUT, +PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,,USART1_CTS,,,USB_DM,,TIM1_BKIN2,,,EVENTOUT, +PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS_DE,LPUART1_RX,,USB_DP,,,,,EVENTOUT, +PortA,PA13,JTMS/SWDIO,,,,,,,,IR_OUT,,USB_NOE,,,SAI1_SD_B,,EVENTOUT, +PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,LCD_SEG5,,SAI1_FS_B,,EVENTOUT, +PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,,SPI1_NSS,,,,TSC_G3_IO1,,LCD_SEG17,,,,EVENTOUT, +PortB,PB0,,,,,,,EXT_PA_TX,,,,,,COMP1_OUT,,,EVENTOUT,ADC12_IN8 +PortB,PB1,,,,,,,,,LPUART1_RTS_DE,,,,,,LPTIM2_IN1,EVENTOUT,ADC12_IN9 +PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,SPI1_NSS,,,,,,LCD_VLCD,,SAI1_EXTCLK,,EVENTOUT, +PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,,USART1_RTS_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT, +PortB,PB4,NJTRST,,,,I2C3_SDA,SPI1_MISO,,USART1_CTS,,TSC_G2_IO1,,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT, +PortB,PB5,,LPTIM1_IN1,,,I2C1_SMBA,SPI1_MOSI,,USART1_CK,LPUART1_TX,TSC_G2_IO2,,LCD_SEG9,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT, +PortB,PB6,MCO,LPTIM1_ETR,,,I2C1_SCL,,,USART1_TX,,TSC_G2_IO3,,LCD_SEG6,,SAI1_FS_B,TIM16_CH1N,EVENTOUT, +PortB,PB7,,LPTIM1_IN2,,TIM1_BKIN,I2C1_SDA,,,USART1_RX,,TSC_G2_IO4,,LCD_SEG21,,,TIM17_CH1N,EVENTOUT, +PortB,PB8,,TIM1_CH2N,,SAI1_PDM_CK1,I2C1_SCL,,,,,,QUADSPI_BK1_IO1,LCD_SEG16,,SAI1_MCLK_A,TIM16_CH1,EVENTOUT, +PortB,PB9,,TIM1_CH3N,,SAI1_PDM_DI2,I2C1_SDA,SPI2_NSS,,,IR_OUT,TSC_G7_IO4,QUADSPI_BK1_IO0,LCD_COM3,,SAI1_FS_A,TIM17_CH1,EVENTOUT, +PortB,PB10,,TIM2_CH3,,,I2C3_SCL,SPI2_SCK,,,LPUART1_RX,TSC_SYNC,QUADSPI_CLK,LCD_SEG10,COMP1_OUT,SAI1_SCK_A,,EVENTOUT, +PortB,PB11,,TIM2_CH4,,,I2C3_SDA,,,,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG11,COMP2_OUT,,,EVENTOUT, +PortB,PB12,,TIM1_BKIN,,TIM1_BKIN,I2C3_SMBA,SPI2_NSS,,,LPUART1_RTS,TSC_G1_IO1,,LCD_SEG12,,SAI1_FS_A,,EVENTOUT, +PortB,PB13,,TIM1_CH1N,,,I2C3_SCL,SPI2_SCK,,,LPUART1_CTS,TSC_G1_IO2,,LCD_SEG13,,SAI1_SCK_A,,EVENTOUT, +PortB,PB14,,TIM1_CH2N,,,I2C3_SDA,SPI2_MISO,,,,TSC_G1_IO3,,LCD_SEG14,,SAI1_MCLK_A,,EVENTOUT, +PortB,PB15,RTC_REFIN,TIM1_CH3N,,,,SPI2_MOSI,,,,TSC_G1_IO4,,LCD_SEG15,,SAI1_SD_A,,EVENTOUT, +PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC123_IN10 +PortC,PC1,,LPTIM1_OUT,,SPI2_MOSI,I2C3_SDA,,,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT,ADC123_IN11 +PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,,,,,,LCD_SEG20,,,,EVENTOUT,ADC123_IN12 +PortC,PC3,,LPTIM1_ETR,,SAI1_PDM_DI1,,SPI2_MOSI,,,,,,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC123_IN13 +PortC,PC4,,,,,,,,,,,,LCD_SEG22,,,,EVENTOUT,ADC12_IN14 +PortC,PC5,,,,SAI1_PDM_DI3,,,,,,,,LCD_SEG23,,,,EVENTOUT,ADC12_IN15 +PortC,PC6,,,,,,,,,,TSC_G4_IO1,,LCD_SEG24,,,,EVENTOUT, +PortC,PC7,,,,,,,,,,TSC_G4_IO2,,LCD_SEG25,,,,EVENTOUT, +PortC,PC8,,,,,,,,,,TSC_G4_IO3,,LCD_SEG26,,,,EVENTOUT, +PortC,PC9,,,,TIM1_BKIN,,,,,,TSC_G4_IO4,USB_NOE,LCD_SEG27,,SAI1_SCK_B,,EVENTOUT, +PortC,PC10,TRACED1,,,,,,,,,TSC_G3_IO2,,LCD_COM4LCD_SEG28LCD_SEG40,,,,EVENTOUT, +PortC,PC11,,,,,,,,,,TSC_G3_IO3,,LCD_COM5LCD_SEG29LCD_SEG41,,,,EVENTOUT, +PortC,PC12,TRACED3,,,,,,,,,TSC_G3_IO4,,LCD_COM6LCD_SEG30LCD_SEG42,,,,EVENTOUT, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, +PortD,PD0,,,,,,SPI2_NSS,,,,,,,,,,EVENTOUT, +PortD,PD1,,,,,,SPI2_SCK,,,,,,,,,,EVENTOUT, +PortD,PD2,TRACED2,,,,,,,,,TSC_SYNC,,LCD_COM7LCD_SEG31LCD_SEG43,,,,EVENTOUT, +PortD,PD3,,,,SPI2_SCK,,SPI2_MISO,,,,,QUADSPI_BK1_NCS,,,,,EVENTOUT, +PortD,PD4,,,,,,SPI2_MOSI,,,,TSC_G5_IO1,QUADSPI_BK1_IO0,,,,,EVENTOUT, +PortD,PD5,,,,,,,,,,TSC_G5_IO2,QUADSPI_BK1_IO1,,,SAI1_MCLK_B,,EVENTOUT, +PortD,PD6,,,,SAI1_PDM_DI1,,,,,,TSC_G5_IO3,QUADSPI_BK1_IO2,,,SAI1_SD_A,,EVENTOUT, +PortD,PD7,,,,,,,,,,TSC_G5_IO4,QUADSPI_BK1_IO3,LCD_SEG39,,,,EVENTOUT, +PortD,PD8,,,TIM1_BKIN2,,,,,,,,,LCD_SEG28,,,,EVENTOUT, +PortD,PD9,TRACED0,,,,,,,,,,,LCD_SEG29,,,,EVENTOUT, +PortD,PD10,TRIG_INOUT,,,,,,,,,TSC_G6_IO1,,LCD_SEG30,,,,EVENTOUT, +PortD,PD11,,,,,,,,,,TSC_G6_IO2,,LCD_SEG31,,,LPTIM2_ETR,EVENTOUT, +PortD,PD12,,,,,,,,,,TSC_G6_IO3,,LCD_SEG32,,,LPTIM2_IN1,EVENTOUT, +PortD,PD13,,,,,,,,,,TSC_G6_IO4,,LCD_SEG33,,,LPTIM2_OUT,EVENTOUT, +PortD,PD14,,TIM1_CH1,,,,,,,,,,LCD_SEG34,,,,EVENTOUT, +PortD,PD15,,TIM1_CH2,,,,,,,,,,LCD_SEG35,,,,EVENTOUT, +PortE,PE0,,TIM1_ETR,,,,,,,,TSC_G7_IO3,,LCD_SEG36,,,TIM16_CH1,EVENTOUT, +PortE,PE1,,,,,,,,,,TSC_G7_IO2,,LCD_SEG37,,,TIM17_CH1,EVENTOUT, +PortE,PE2,TRACECK,,,SAI1_PDM_CK1,,,,,,TSC_G7_IO1,,LCD_SEG38,,SAI1_MCLK_A,,EVENTOUT, +PortE,PE3,,,,,,,,,,,,,,,,EVENTOUT, +PortE,PE4,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH3,LSCO,,,,,,,,,,,,,,,EVENTOUT, diff --git a/ports/stm32/boards/stm32wb55xg.ld b/ports/stm32/boards/stm32wb55xg.ld new file mode 100644 index 0000000000000..bdbf7e447e1d3 --- /dev/null +++ b/ports/stm32/boards/stm32wb55xg.ld @@ -0,0 +1,33 @@ +/* + GNU linker script for STM32WB55xG +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* sectors 0-127 */ + FLASH_FS (r) : ORIGIN = 0x08080000, LENGTH = 256K /* sectors 128-191 */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K /* SRAM1 */ +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_ram_fs_cache_end = ORIGIN(RAM) + LENGTH(RAM); +_ram_fs_cache_start = _ram_fs_cache_end - 4K; /* fs cache = 4K */ + +/* Define the stack. The stack is full descending so begins at the bottom of FS cache. + Note that EABI requires the stack to be 8-byte aligned for a call. */ +_estack = _ram_fs_cache_start - _estack_reserve; +_sstack = _estack - 16K; + +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _sstack; + +_flash_fs_start = ORIGIN(FLASH_FS); +_flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32wbxx_hal_conf_base.h b/ports/stm32/boards/stm32wbxx_hal_conf_base.h new file mode 100644 index 0000000000000..8dbc9ecea7f12 --- /dev/null +++ b/ports/stm32/boards/stm32wbxx_hal_conf_base.h @@ -0,0 +1,78 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32WBXX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32WBXX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32wbxx_hal_dma.h" +#include "stm32wbxx_hal_adc.h" +#include "stm32wbxx_hal_cortex.h" +#include "stm32wbxx_hal_flash.h" +#include "stm32wbxx_hal_gpio.h" +#include "stm32wbxx_hal_i2c.h" +#include "stm32wbxx_hal_pcd.h" +#include "stm32wbxx_hal_pwr.h" +#include "stm32wbxx_hal_rcc.h" +#include "stm32wbxx_hal_rtc.h" +#include "stm32wbxx_hal_spi.h" +#include "stm32wbxx_hal_tim.h" +#include "stm32wbxx_hal_uart.h" +#include "stm32wbxx_hal_usart.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED + +// Oscillator values in Hz +#define MSI_VALUE (4000000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define DATA_CACHE_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define PREFETCH_ENABLE 0 +#define USE_SPI_CRC 0 +#define USE_RTOS 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32WBXX_HAL_CONF_BASE_H From d2a8fb747fbe2ac67cd266f6bc0fcccd9a5874e6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 16:50:59 +1000 Subject: [PATCH 0288/1299] stm32/boards/NUCLEO_WB55: Add definition files for new board. --- .../stm32/boards/NUCLEO_WB55/mpconfigboard.h | 64 +++++++++++++++++++ .../stm32/boards/NUCLEO_WB55/mpconfigboard.mk | 5 ++ ports/stm32/boards/NUCLEO_WB55/pins.csv | 34 ++++++++++ .../boards/NUCLEO_WB55/stm32wbxx_hal_conf.h | 19 ++++++ 4 files changed, 122 insertions(+) create mode 100644 ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h create mode 100644 ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk create mode 100644 ports/stm32/boards/NUCLEO_WB55/pins.csv create mode 100644 ports/stm32/boards/NUCLEO_WB55/stm32wbxx_hal_conf.h diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h new file mode 100644 index 0000000000000..fc047880d1a20 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h @@ -0,0 +1,64 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * MIT License; Copyright (c) 2019 Damien P. George + */ + +#define MICROPY_HW_BOARD_NAME "NUCLEO-WB55" +#define MICROPY_HW_MCU_NAME "STM32WB55RGV6" + +#define MICROPY_PY_PYB_LEGACY (0) + +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_ADC (0) +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_HAS_SWITCH (1) + +// There is an external 32kHz oscillator +#define RTC_ASYNCH_PREDIV (0) +#define RTC_SYNCH_PREDIV (0x7fff) +#define MICROPY_HW_RTC_USE_LSE (1) +#define MICROPY_HW_RTC_USE_US (1) + +// UART buses +#define MICROPY_HW_UART1_TX (pin_B6) +#define MICROPY_HW_UART1_RX (pin_B7) +// USART 1 is connected to the virtual com port on the ST-LINK +#define MICROPY_HW_UART_REPL PYB_UART_1 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C buses +#define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10 +#define MICROPY_HW_I2C1_SDA (pin_B9) // Arduino D14, pin 5 on CN10 +#define MICROPY_HW_I2C3_SCL (pin_C0) // Arduino A0, pin 28 on CN7 +#define MICROPY_HW_I2C3_SDA (pin_C1) // Arduino A1, pin 30 on CN7 + +// SPI buses +#if 0 // TODO need working DMA +#define MICROPY_HW_SPI1_NSS (pin_A4) // Arduino D10 pin 17 on CN10 +#define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10 +#define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10 +#define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10 +#define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10 +#define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10 +#define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10 +#define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10 +#endif + +// User switch; pressing the button makes the input go low +#define MICROPY_HW_USRSW_PIN (pin_C4) +#define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// LEDs +#define MICROPY_HW_LED1 (pin_B1) // red +#define MICROPY_HW_LED2 (pin_B0) // green +#define MICROPY_HW_LED3 (pin_B5) // blue +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// USB config +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_HID (0) +#define USBD_CDC_RX_DATA_SIZE (512) +#define USBD_CDC_TX_DATA_SIZE (512) diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk new file mode 100644 index 0000000000000..b0f93c006f2ec --- /dev/null +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk @@ -0,0 +1,5 @@ +MCU_SERIES = wb +CMSIS_MCU = STM32WB55xx +AF_FILE = boards/stm32wb55_af.csv +LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld +STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.o diff --git a/ports/stm32/boards/NUCLEO_WB55/pins.csv b/ports/stm32/boards/NUCLEO_WB55/pins.csv new file mode 100644 index 0000000000000..49fdab0c28c58 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_WB55/pins.csv @@ -0,0 +1,34 @@ +,PA0 +,PA1 +,PA2 +,PA3 +,PA4 +,PA5 +,PA6 +,PA7 +,PB0 +,PB1 +,PB2 +,PB3 +,PB4 +,PB5 +,PB6 +,PB7 +,PB8 +,PB9 +,PB10 +,PB11 +,PB12 +,PB13 +,PB14 +,PB15 +,PC0 +,PC1 +,PC2 +,PC3 +SW,PC4 +LED_GREEN,PB0 +LED_RED,PB1 +LED_BLUE,PB5 +USB_DM,PA11 +USB_DP,PA12 diff --git a/ports/stm32/boards/NUCLEO_WB55/stm32wbxx_hal_conf.h b/ports/stm32/boards/NUCLEO_WB55/stm32wbxx_hal_conf.h new file mode 100644 index 0000000000000..176857220eb8d --- /dev/null +++ b/ports/stm32/boards/NUCLEO_WB55/stm32wbxx_hal_conf.h @@ -0,0 +1,19 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H + +// Oscillator values in Hz +#define HSE_VALUE (32000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#include "boards/stm32wbxx_hal_conf_base.h" + +#endif // MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H From 0c12adca4611c35763b7aaff1c7a4d76d160a29e Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 16:51:24 +1000 Subject: [PATCH 0289/1299] stm32/boards/USBDONGLE_WB55: Add definition files for new board. --- .../boards/USBDONGLE_WB55/mpconfigboard.h | 43 +++++++++++++++++++ .../boards/USBDONGLE_WB55/mpconfigboard.mk | 5 +++ ports/stm32/boards/USBDONGLE_WB55/pins.csv | 32 ++++++++++++++ .../USBDONGLE_WB55/stm32wbxx_hal_conf.h | 19 ++++++++ 4 files changed, 99 insertions(+) create mode 100644 ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h create mode 100644 ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk create mode 100644 ports/stm32/boards/USBDONGLE_WB55/pins.csv create mode 100644 ports/stm32/boards/USBDONGLE_WB55/stm32wbxx_hal_conf.h diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h new file mode 100644 index 0000000000000..77e2d4f3299a7 --- /dev/null +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h @@ -0,0 +1,43 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * MIT License; Copyright (c) 2019 Damien P. George + */ + +#define MICROPY_HW_BOARD_NAME "USBDongle-WB55" +#define MICROPY_HW_MCU_NAME "STM32WB55CGU6" + +#define MICROPY_PY_PYB_LEGACY (0) + +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_ADC (0) +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_HAS_SWITCH (1) + +// There is an external 32kHz oscillator +#define RTC_ASYNCH_PREDIV (0) +#define RTC_SYNCH_PREDIV (0x7fff) +#define MICROPY_HW_RTC_USE_LSE (1) +#define MICROPY_HW_RTC_USE_US (1) + +// I2C buses +#define MICROPY_HW_I2C1_SCL (pin_B8) +#define MICROPY_HW_I2C1_SDA (pin_B9) + +// User switch; pressing the button makes the input go low +#define MICROPY_HW_USRSW_PIN (pin_A10) +#define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// LEDs +#define MICROPY_HW_LED1 (pin_B1) // red +#define MICROPY_HW_LED2 (pin_B0) // green +#define MICROPY_HW_LED3 (pin_A4) // blue +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// USB config +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_HID (0) +#define USBD_CDC_RX_DATA_SIZE (512) +#define USBD_CDC_TX_DATA_SIZE (512) diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk new file mode 100644 index 0000000000000..b0f93c006f2ec --- /dev/null +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk @@ -0,0 +1,5 @@ +MCU_SERIES = wb +CMSIS_MCU = STM32WB55xx +AF_FILE = boards/stm32wb55_af.csv +LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld +STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.o diff --git a/ports/stm32/boards/USBDONGLE_WB55/pins.csv b/ports/stm32/boards/USBDONGLE_WB55/pins.csv new file mode 100644 index 0000000000000..2b115c5c40fe6 --- /dev/null +++ b/ports/stm32/boards/USBDONGLE_WB55/pins.csv @@ -0,0 +1,32 @@ +,PA0 +,PA1 +,PA2 +,PA3 +,PA4 +,PA5 +,PA6 +,PA7 +,PA8 +,PA9 +,PA10 +,PA11 +,PA12 +,PA13 +,PA14 +,PA15 +,PB0 +,PB1 +,PB2 +,PB3 +,PB4 +,PB5 +,PB6 +,PB7 +,PB8 +,PB9 +SW,PA10 +LED_GREEN,PB0 +LED_RED,PB1 +LED_BLUE,PA4 +USB_DM,PA11 +USB_DP,PA12 diff --git a/ports/stm32/boards/USBDONGLE_WB55/stm32wbxx_hal_conf.h b/ports/stm32/boards/USBDONGLE_WB55/stm32wbxx_hal_conf.h new file mode 100644 index 0000000000000..176857220eb8d --- /dev/null +++ b/ports/stm32/boards/USBDONGLE_WB55/stm32wbxx_hal_conf.h @@ -0,0 +1,19 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H + +// Oscillator values in Hz +#define HSE_VALUE (32000000) +#define LSE_VALUE (32768) +#define EXTERNAL_SAI1_CLOCK_VALUE (48000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#include "boards/stm32wbxx_hal_conf_base.h" + +#endif // MICROPY_INCLUDED_STM32WBXX_HAL_CONF_H From 3967dd68e80b296d1beead5e630807d914d98de6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 19 Jul 2019 14:07:41 +1000 Subject: [PATCH 0290/1299] tests/run-perfbench.py: Add --emit option to select emitter for tests. --- tests/run-perfbench.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index d8100ef81d194..e52aa0ccbc07a 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -49,7 +49,7 @@ def run_script_on_target(target, script): else: # Run local executable try: - p = subprocess.run([target], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, input=script) + p = subprocess.run(target, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, input=script) output = p.stdout except subprocess.CalledProcessError as er: err = er @@ -195,6 +195,7 @@ def main(): cmd_parser.add_argument('-p', '--pyboard', action='store_true', help='run tests via pyboard.py') cmd_parser.add_argument('-d', '--device', default='/dev/ttyACM0', help='the device for pyboard.py') cmd_parser.add_argument('-a', '--average', default='8', help='averaging number') + cmd_parser.add_argument('--emit', default='bytecode', help='MicroPython emitter to use (bytecode or native)') cmd_parser.add_argument('N', nargs=1, help='N parameter (approximate target CPU frequency)') cmd_parser.add_argument('M', nargs=1, help='M parameter (approximate target heap in kbytes)') cmd_parser.add_argument('files', nargs='*', help='input test files') @@ -215,7 +216,7 @@ def main(): target = pyboard.Pyboard(args.device) target.enter_raw_repl() else: - target = MICROPYTHON + target = [MICROPYTHON, '-X', 'emit=' + args.emit] if len(args.files) == 0: tests_skip = ('benchrun.py',) From a29334761dc7b8eaf9f78611e3cd9033928b110c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Jul 2019 13:43:52 +1000 Subject: [PATCH 0291/1299] esp32: Add support for hardware I2C. --- docs/esp32/quickref.rst | 14 ++- ports/esp32/Makefile | 1 + ports/esp32/machine_i2c.c | 179 +++++++++++++++++++++++++++++++++++++ ports/esp32/mpconfigport.h | 1 + 4 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 ports/esp32/machine_i2c.c diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 76fe0d9f9ed41..dd85b102b2551 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -303,14 +303,22 @@ Hardware SPI has the same methods as Software SPI above:: I2C bus ------- -The I2C driver is implemented in software and works on all pins, -and is accessed via the :ref:`machine.I2C ` class:: +The I2C driver has both software and hardware implementations, and the two +hardware peripherals have identifiers 0 and 1. Any available output-capable +pins can be used for SCL and SDA. The driver is accessed via the +:ref:`machine.I2C ` class:: from machine import Pin, I2C - # construct an I2C bus + # construct a software I2C bus i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000) + # construct a hardware I2C bus + i2c = I2C(0) + i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000) + + i2c.scan() # scan for slave devices + i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index ec6d29695b13d..4ce4e489900f1 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -181,6 +181,7 @@ SRC_C = \ machine_touchpad.c \ machine_adc.c \ machine_dac.c \ + machine_i2c.c \ machine_pwm.c \ machine_uart.c \ modmachine.c \ diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c new file mode 100644 index 0000000000000..b34d24b16f012 --- /dev/null +++ b/ports/esp32/machine_i2c.c @@ -0,0 +1,179 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" +#include "py/mperrno.h" +#include "extmod/machine_i2c.h" + +#include "driver/i2c.h" + +#define I2C_0_DEFAULT_SCL (GPIO_NUM_18) +#define I2C_0_DEFAULT_SDA (GPIO_NUM_19) +#define I2C_1_DEFAULT_SCL (GPIO_NUM_25) +#define I2C_1_DEFAULT_SDA (GPIO_NUM_26) + +#define I2C_DEFAULT_TIMEOUT_US (10000) // 10ms + +typedef struct _machine_hw_i2c_obj_t { + mp_obj_base_t base; + i2c_port_t port : 8; + gpio_num_t scl : 8; + gpio_num_t sda : 8; +} machine_hw_i2c_obj_t; + +STATIC const mp_obj_type_t machine_hw_i2c_type; +STATIC machine_hw_i2c_obj_t machine_hw_i2c_obj[I2C_NUM_MAX]; + +STATIC void machine_hw_i2c_init(machine_hw_i2c_obj_t *self, uint32_t freq, uint32_t timeout_us, bool first_init) { + if (!first_init) { + i2c_driver_delete(self->port); + } + i2c_config_t conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = self->sda, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_io_num = self->scl, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = freq, + }; + i2c_param_config(self->port, &conf); + i2c_set_timeout(self->port, I2C_APB_CLK_FREQ / 1000000 * timeout_us); + i2c_driver_install(self->port, I2C_MODE_MASTER, 0, 0, 0); +} + +int machine_hw_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { + machine_hw_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, addr << 1 | (flags & MP_MACHINE_I2C_FLAG_READ), true); + + int data_len = 0; + for (; n--; ++bufs) { + if (flags & MP_MACHINE_I2C_FLAG_READ) { + i2c_master_read(cmd, bufs->buf, bufs->len, n == 0 ? I2C_MASTER_LAST_NACK : I2C_MASTER_ACK); + } else { + if (bufs->len != 0) { + i2c_master_write(cmd, bufs->buf, bufs->len, true); + } + } + data_len += bufs->len; + } + + if (flags & MP_MACHINE_I2C_FLAG_STOP) { + i2c_master_stop(cmd); + } + + // TODO proper timeout + esp_err_t err = i2c_master_cmd_begin(self->port, cmd, 100 * (1 + data_len) / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + + if (err == ESP_FAIL) { + return -MP_ENODEV; + } else if (err == ESP_ERR_TIMEOUT) { + return -MP_ETIMEDOUT; + } else if (err != ESP_OK) { + return -abs(err); + } + + return data_len; +} + +/******************************************************************************/ +// MicroPython bindings for machine API + +STATIC void machine_hw_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_hw_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + int h, l; + i2c_get_period(self->port, &h, &l); + mp_printf(print, "I2C(%u, scl=%u, sda=%u, freq=%u)", + self->port, self->scl, self->sda, I2C_APB_CLK_FREQ / (h + l)); +} + +mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // Parse args + enum { ARG_id, ARG_scl, ARG_sda, ARG_freq, ARG_timeout }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_DEFAULT_TIMEOUT_US} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Get I2C bus + mp_int_t i2c_id = mp_obj_get_int(args[ARG_id].u_obj); + if (!(I2C_NUM_0 <= i2c_id && i2c_id < I2C_NUM_MAX)) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C(%d) doesn't exist", i2c_id)); + } + + // Get static peripheral object + machine_hw_i2c_obj_t *self = (machine_hw_i2c_obj_t*)&machine_hw_i2c_obj[i2c_id]; + + bool first_init = false; + if (self->base.type == NULL) { + // Created for the first time, set default pins + self->base.type = &machine_hw_i2c_type; + self->port = i2c_id; + if (self->port == I2C_NUM_0) { + self->scl = I2C_0_DEFAULT_SCL; + self->sda = I2C_0_DEFAULT_SDA; + } else { + self->scl = I2C_1_DEFAULT_SCL; + self->sda = I2C_1_DEFAULT_SDA; + } + first_init = true; + } + + // Set SCL/SDA pins if given + if (args[ARG_scl].u_obj != MP_OBJ_NULL) { + self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj); + } + if (args[ARG_sda].u_obj != MP_OBJ_NULL) { + self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj); + } + + // Initialise the I2C peripheral + machine_hw_i2c_init(self, args[ARG_freq].u_int, args[ARG_timeout].u_int, first_init); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC const mp_machine_i2c_p_t machine_hw_i2c_p = { + .transfer = machine_hw_i2c_transfer, +}; + +STATIC const mp_obj_type_t machine_hw_i2c_type = { + { &mp_type_type }, + .name = MP_QSTR_I2C, + .print = machine_hw_i2c_print, + .make_new = machine_hw_i2c_make_new, + .protocol = &machine_hw_i2c_p, + .locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict, +}; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index bd19c6bfbdb2d..9ffe380fca063 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -137,6 +137,7 @@ #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hw_i2c_make_new #define MICROPY_PY_MACHINE_SPI (1) #define MICROPY_PY_MACHINE_SPI_MSB (0) #define MICROPY_PY_MACHINE_SPI_LSB (1) From 9da46a98cbd20ea8cc48fc2378bf8092abd80795 Mon Sep 17 00:00:00 2001 From: stijn Date: Wed, 17 Jul 2019 12:08:40 +0200 Subject: [PATCH 0292/1299] windows/mpconfigport.h: Don't define restrict/inline/alignof for C++. The C++ standard forbids redefining keywords, like inline and alignof, so guard these definitions to avoid that, allowing to include the MicroPython headers by C++ code. --- ports/windows/mpconfigport.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 86e44183bfeb5..ffe7ae1443afb 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -228,9 +228,11 @@ extern const struct _mp_obj_module_t mp_module_time; // CL specific definitions +#ifndef __cplusplus #define restrict #define inline __inline #define alignof(t) __alignof(t) +#endif #define PATH_MAX MICROPY_ALLOC_PATH_MAX #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) From 331c224e07f5786e0ea814ed1e840ffa714c14fd Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 11 Jul 2019 14:57:40 +1000 Subject: [PATCH 0293/1299] esp32/Makefile: Fix path expansion for ESPIDF_DRIVER_O. It was using subst to s/.c/.o/ which changed .c anywhere in the path. --- ports/esp32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 4ce4e489900f1..2d2db368a3085 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -257,7 +257,7 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) ################################################################################ # List of object files from the ESP32 IDF components -ESPIDF_DRIVER_O = $(subst .c,.o,$(wildcard $(ESPCOMP)/driver/*.c)) +ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) ESPIDF_EFUSE_O = $(addprefix $(ESPCOMP)/efuse/,\ esp32/esp_efuse_table.o \ From b88e51d718892f3f2fe185e40d949428ef89267d Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 20 Jul 2019 13:02:11 +1000 Subject: [PATCH 0294/1299] esp32/Makefile: Put OBJ and LIB rule additions in gen_espidf_lib_rule. --- ports/esp32/Makefile | 78 +++++++------------------------------------- 1 file changed, 12 insertions(+), 66 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 2d2db368a3085..cbb653a582850 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -678,76 +678,12 @@ ESPIDF_SDMMC_O = $(addprefix $(ESPCOMP)/sdmmc/,\ ) OBJ_ESPIDF = -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_DRIVER_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_EFUSE_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP32_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP_RINGBUF_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_HEAP_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SOC_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_CXX_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ETHERNET_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_EXPAT_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_PTHREAD_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_FREERTOS_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_VFS_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_JSON_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_LOG_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_LWIP_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_MBEDTLS_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_XTENSA_DEBUG_MODULE_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_TCPIP_ADAPTER_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_APP_TRACE_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_APP_UPDATE_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NGHTTP_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NVS_FLASH_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_OPENSSL_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SMARTCONFIG_ACK_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SPI_FLASH_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ULP_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_WPA_SUPPLICANT_O)) -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SDMMC_O)) - -$(OBJ_ESPIDF): $(SDKCONFIG_H) - LIB_ESPIDF = -LIB_ESPIDF += driver -LIB_ESPIDF += efuse -LIB_ESPIDF += esp32 -LIB_ESPIDF += esp_ringbuf -LIB_ESPIDF += heap -LIB_ESPIDF += soc -LIB_ESPIDF += cxx -LIB_ESPIDF += ethernet -LIB_ESPIDF += expat -LIB_ESPIDF += pthread -LIB_ESPIDF += freertos -LIB_ESPIDF += vfs -LIB_ESPIDF += json -LIB_ESPIDF += log -LIB_ESPIDF += xtensa-debug-module -LIB_ESPIDF += tcpip_adapter -LIB_ESPIDF += app_trace -LIB_ESPIDF += app_update -LIB_ESPIDF += newlib -LIB_ESPIDF += nghttp -LIB_ESPIDF += nvs_flash -LIB_ESPIDF += smartconfig_ack -LIB_ESPIDF += spi_flash -LIB_ESPIDF += ulp -LIB_ESPIDF += lwip -LIB_ESPIDF += mbedtls -LIB_ESPIDF += wpa_supplicant -LIB_ESPIDF += sdmmc - BUILD_ESPIDF_LIB = $(BUILD)/esp-idf -OBJ_ESPIDF_DIRS = $(sort $(dir $(OBJ_ESPIDF))) $(BUILD_ESPIDF_LIB) $(addprefix $(BUILD_ESPIDF_LIB)/,$(LIB_ESPIDF)) -$(OBJ_ESPIDF): | $(OBJ_ESPIDF_DIRS) -$(OBJ_ESPIDF_DIRS): - $(MKDIR) -p $@ - define gen_espidf_lib_rule +OBJ_ESPIDF += $(addprefix $$(BUILD)/,$(2)) +LIB_ESPIDF += $(1) $(BUILD_ESPIDF_LIB)/$(1)/lib$(1).a: $(addprefix $$(BUILD)/,$(2)) $(ECHO) "AR $$@" $(Q)$(AR) cru $$@ $$^ @@ -782,6 +718,16 @@ $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) +# Create all destination build dirs before compiling IDF source +OBJ_ESPIDF_DIRS = $(sort $(dir $(OBJ_ESPIDF))) $(BUILD_ESPIDF_LIB) $(addprefix $(BUILD_ESPIDF_LIB)/,$(LIB_ESPIDF)) +$(OBJ_ESPIDF): | $(OBJ_ESPIDF_DIRS) +$(OBJ_ESPIDF_DIRS): + $(MKDIR) -p $@ + +# Make all IDF object files depend on sdkconfig +$(OBJ_ESPIDF): $(SDKCONFIG_H) + +# Add all IDF components to the set of libraries LIB = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) ################################################################################ From e3e7e3a781addf8743b783b9f1d464448f1c94bb Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 20 Jul 2019 13:04:20 +1000 Subject: [PATCH 0295/1299] esp32/Makefile: Simplify include of IDF source by using wildcards. --- ports/esp32/Makefile | 427 ++++++------------------------------------- 1 file changed, 51 insertions(+), 376 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index cbb653a582850..cb8c88a2d794d 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -259,109 +259,34 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) -ESPIDF_EFUSE_O = $(addprefix $(ESPCOMP)/efuse/,\ - esp32/esp_efuse_table.o \ - src/esp_efuse_api.o \ - src/esp_efuse_utility.o \ +ESPIDF_EFUSE_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/efuse/esp32/*.c)\ + $(wildcard $(ESPCOMP)/efuse/src/*.c)\ ) $(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds -ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ - brownout.o \ - cache_sram_mmu.o \ - coexist.o \ - dbg_stubs.o \ - dport_panic_highint_hdl.o \ - esp_adapter.o \ - esp_err_to_name.o \ - esp_himem.o \ - panic.o \ - pm_trace.o \ - reset_reason.o \ - restore.o \ - stack_check.o \ - esp_timer.o \ - esp_timer_esp32.o \ - ets_timer_legacy.o \ - event_default_handlers.o \ - fast_crypto_ops.o \ - task_wdt.o \ - cache_err_int.o \ - clk.o \ - cpu_start.o \ - gdbstub.o \ - crosscore_int.o \ - ipc.o \ - int_wdt.o \ - event_loop.o \ - hwcrypto/sha.o \ - hwcrypto/aes.o \ - lib_printf.o \ - freertos_hooks.o \ - system_api.o \ - hw_random.o \ - phy_init.o \ - pm_esp32.o \ - pm_locks.o \ - intr_alloc.o \ - dport_access.o \ - wifi_init.o \ - sleep_modes.o \ - spiram.o \ - spiram_psram.o \ - ) +ESPIDF_ESP32_O = \ + $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/*.c)) \ + $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp32/hwcrypto/*.c)) \ + $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/esp32/*.S)) \ -ESPIDF_ESP_RINGBUF_O = $(addprefix $(ESPCOMP)/esp_ringbuf/,\ - ringbuf.o \ - ) +ESPIDF_ESP_RINGBUF_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_ringbuf/*.c)) -ESPIDF_HEAP_O = $(addprefix $(ESPCOMP)/heap/,\ - heap_caps.o \ - heap_caps_init.o \ - multi_heap.o \ - ) +ESPIDF_HEAP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/heap/*.c)) -ESPIDF_SOC_O = $(addprefix $(ESPCOMP)/soc/,\ - esp32/cpu_util.o \ - esp32/gpio_periph.o \ - esp32/rtc_clk.o \ - esp32/rtc_init.o \ - esp32/rtc_periph.o \ - esp32/rtc_pm.o \ - esp32/rtc_sleep.o \ - esp32/rtc_time.o \ - esp32/rtc_wdt.o \ - esp32/sdmmc_periph.o \ - esp32/soc_memory_layout.o \ - esp32/spi_periph.o \ - src/memory_layout_utils.o \ - ) - -ESPIDF_CXX_O = $(addprefix $(ESPCOMP)/cxx/,\ - cxx_guards.o \ +ESPIDF_SOC_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/soc/esp32/*.c) \ + $(wildcard $(ESPCOMP)/soc/src/*.c) \ ) -ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\ - emac_dev.o \ - emac_main.o \ - eth_phy/phy_tlk110.o \ - eth_phy/phy_lan8720.o \ - eth_phy/phy_common.o \ - ) +ESPIDF_CXX_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/cxx/*.cpp)) -$(BUILD)/$(ESPCOMP)/expat/%.o: CFLAGS += -DHAVE_EXPAT_CONFIG_H -DHAVE_GETRANDOM -ESPIDF_EXPAT_O = $(addprefix $(ESPCOMP)/expat/,\ - expat/expat/lib/xmltok_ns.o \ - expat/expat/lib/xmltok.o \ - expat/expat/lib/xmlparse.o \ - expat/expat/lib/xmlrole.o \ - expat/expat/lib/xmltok_impl.o \ +ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/ethernet/*.c) \ + $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ ) -ESPIDF_PTHREAD_O = $(addprefix $(ESPCOMP)/pthread/,\ - pthread.o \ - pthread_local_storage.o \ - ) +ESPIDF_PTHREAD_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/pthread/*.c)) # Assembler .S files need only basic flags, and in particular should not have # -Os because that generates subtly different code. @@ -374,308 +299,60 @@ $(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_vectors.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_vector_defaults.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/%.o: CFLAGS = $(CFLAGS_BASE) -I. -I$(BUILD) $(INC_ESPCOMP) -I$(ESPCOMP)/freertos/include/freertos -D_ESP_FREERTOS_INTERNAL -ESPIDF_FREERTOS_O = $(addprefix $(ESPCOMP)/freertos/,\ - croutine.o \ - event_groups.o \ - FreeRTOS-openocd.o \ - list.o \ - portasm.o \ - port.o \ - queue.o \ - tasks.o \ - timers.o \ - xtensa_context.o \ - xtensa_init.o \ - xtensa_intr_asm.o \ - xtensa_intr.o \ - xtensa_overlay_os_hook.o \ - xtensa_vector_defaults.o \ - xtensa_vectors.o \ - ) +ESPIDF_FREERTOS_O = \ + $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/freertos/*.c)) \ + $(patsubst %.S,%.o,$(wildcard $(ESPCOMP)/freertos/*.S)) \ -ESPIDF_VFS_O = $(addprefix $(ESPCOMP)/vfs/,\ - vfs_uart.o \ - vfs.o \ - ) +ESPIDF_VFS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/vfs/*.c)) -ESPIDF_JSON_O = $(addprefix $(ESPCOMP)/json/cJSON/,\ - cJSON.o \ - cJSON_Utils.o \ - ) +ESPIDF_JSON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/json/cJSON/cJSON*.c)) -ESPIDF_LOG_O = $(addprefix $(ESPCOMP)/log/,\ - log.o \ - ) +ESPIDF_LOG_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/log/*.c)) -ESPIDF_XTENSA_DEBUG_MODULE_O = $(addprefix $(ESPCOMP)/xtensa-debug-module/,\ - eri.o \ - trax.o \ - ) +ESPIDF_XTENSA_DEBUG_MODULE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/xtensa-debug-module/*.c)) -ESPIDF_TCPIP_ADAPTER_O = $(addprefix $(ESPCOMP)/tcpip_adapter/,\ - tcpip_adapter_lwip.o \ - ) +ESPIDF_TCPIP_ADAPTER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/tcpip_adapter/*.c)) -ESPIDF_APP_TRACE_O = $(addprefix $(ESPCOMP)/app_trace/,\ - app_trace.o \ - ) +ESPIDF_APP_TRACE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_trace/*.c)) -ESPIDF_APP_UPDATE_O = $(addprefix $(ESPCOMP)/app_update/,\ - esp_app_desc.o \ - esp_ota_ops.o \ - ) +ESPIDF_APP_UPDATE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_update/*.c)) -ESPIDF_NEWLIB_O = $(addprefix $(ESPCOMP)/newlib/,\ - time.o \ - select.o \ - syscalls.o \ - syscall_table.o \ - reent_init.o \ - locks.o \ - ) +ESPIDF_NEWLIB_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/newlib/*.c)) -ESPIDF_NGHTTP_O = $(addprefix $(ESPCOMP)/nghttp/,\ - nghttp2/lib/nghttp2_http.o \ - nghttp2/lib/nghttp2_version.o \ - nghttp2/lib/nghttp2_mem.o \ - nghttp2/lib/nghttp2_hd_huffman.o \ - nghttp2/lib/nghttp2_rcbuf.o \ - nghttp2/lib/nghttp2_callbacks.o \ - nghttp2/lib/nghttp2_session.o \ - nghttp2/lib/nghttp2_stream.o \ - nghttp2/lib/nghttp2_hd.o \ - nghttp2/lib/nghttp2_priority_spec.o \ - nghttp2/lib/nghttp2_buf.o \ - nghttp2/lib/nghttp2_option.o \ - nghttp2/lib/nghttp2_npn.o \ - nghttp2/lib/nghttp2_helper.o \ - nghttp2/lib/nghttp2_frame.o \ - nghttp2/lib/nghttp2_outbound_item.o \ - nghttp2/lib/nghttp2_hd_huffman_data.o \ - nghttp2/lib/nghttp2_pq.o \ - nghttp2/lib/nghttp2_queue.o \ - nghttp2/lib/nghttp2_submit.o \ - nghttp2/lib/nghttp2_map.o \ - port/http_parser.o \ - ) +ESPIDF_NVS_FLASH_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/nvs_flash/src/*.cpp)) -ESPIDF_NVS_FLASH_O = $(addprefix $(ESPCOMP)/nvs_flash/,\ - src/nvs_ops.o \ - src/nvs_types.o \ - src/nvs_page.o \ - src/nvs_item_hash_list.o \ - src/nvs_pagemanager.o \ - src/nvs_storage.o \ - src/nvs_api.o \ - ) +ESPIDF_SMARTCONFIG_ACK_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/smartconfig_ack/*.c)) -ESPIDF_OPENSSL_O = $(addprefix $(ESPCOMP)/openssl/,\ - ) +ESPIDF_SPI_FLASH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/spi_flash/*.c)) -ESPIDF_SMARTCONFIG_ACK_O = $(addprefix $(ESPCOMP)/smartconfig_ack/,\ - smartconfig_ack.o \ - ) - -ESPIDF_SPI_FLASH_O = $(addprefix $(ESPCOMP)/spi_flash/,\ - flash_mmap.o \ - partition.o \ - spi_flash_rom_patch.o \ - cache_utils.o \ - flash_ops.o \ - ) - -ESPIDF_ULP_O = $(addprefix $(ESPCOMP)/ulp/,\ - ulp.o \ - ) +ESPIDF_ULP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/ulp/*.c)) $(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable -ESPIDF_LWIP_O = $(addprefix $(ESPCOMP)/lwip/,\ - apps/dhcpserver/dhcpserver.o \ - lwip/src/api/netbuf.o \ - lwip/src/api/api_lib.o \ - lwip/src/api/netifapi.o \ - lwip/src/api/tcpip.o \ - lwip/src/api/netdb.o \ - lwip/src/api/err.o \ - lwip/src/api/api_msg.o \ - lwip/src/api/sockets.o \ - lwip/src/apps/sntp/sntp.o \ - lwip/src/core/ipv4/dhcp.o \ - lwip/src/core/ipv4/etharp.o \ - lwip/src/core/ipv4/ip4_addr.o \ - lwip/src/core/ipv4/igmp.o \ - lwip/src/core/ipv4/ip4.o \ - lwip/src/core/ipv4/autoip.o \ - lwip/src/core/ipv4/icmp.o \ - lwip/src/core/ipv6/ip6_frag.o \ - lwip/src/core/ipv6/dhcp6.o \ - lwip/src/core/ipv6/inet6.o \ - lwip/src/core/ipv6/ip6_addr.o \ - lwip/src/core/ipv6/ip6.o \ - lwip/src/core/ipv6/nd6.o \ - lwip/src/core/ipv6/mld6.o \ - lwip/src/core/ipv6/ethip6.o \ - lwip/src/core/ipv6/icmp6.o \ - lwip/src/core/mem.o \ - lwip/src/core/init.o \ - lwip/src/core/memp.o \ - lwip/src/core/sys.o \ - lwip/src/core/tcp_in.o \ - lwip/src/core/timeouts.o \ - lwip/src/core/dns.o \ - lwip/src/core/ip.o \ - lwip/src/core/pbuf.o \ - lwip/src/core/raw.o \ - lwip/src/core/tcp.o \ - lwip/src/core/def.o \ - lwip/src/core/netif.o \ - lwip/src/core/stats.o \ - lwip/src/core/inet_chksum.o \ - lwip/src/core/udp.o \ - lwip/src/core/tcp_out.o \ - lwip/src/netif/slipif.o \ - lwip/src/netif/ethernet.o \ - lwip/src/netif/lowpan6.o \ - lwip/src/netif/ethernetif.o \ - lwip/src/netif/ppp/auth.o \ - lwip/src/netif/ppp/chap-md5.o \ - lwip/src/netif/ppp/chap-new.o \ - lwip/src/netif/ppp/fsm.o \ - lwip/src/netif/ppp/ipcp.o \ - lwip/src/netif/ppp/ipv6cp.o \ - lwip/src/netif/ppp/lcp.o \ - lwip/src/netif/ppp/magic.o \ - lwip/src/netif/ppp/polarssl/md5.o \ - lwip/src/netif/ppp/ppp.o \ - lwip/src/netif/ppp/pppapi.o \ - lwip/src/netif/ppp/pppos.o \ - lwip/src/netif/ppp/upap.o \ - lwip/src/netif/ppp/utils.o \ - lwip/src/netif/ppp/vj.o \ - port/esp32/freertos/sys_arch.o \ - port/esp32/netif/ethernetif.o \ - port/esp32/netif/wlanif.o \ - port/esp32/vfs_lwip.o \ +ESPIDF_LWIP_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/lwip/apps/dhcpserver/*.c) \ + $(wildcard $(ESPCOMP)/lwip/lwip/src/api/*.c) \ + $(wildcard $(ESPCOMP)/lwip/lwip/src/apps/sntp/*.c) \ + $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*.c) \ + $(wildcard $(ESPCOMP)/lwip/lwip/src/core/*/*.c) \ + $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*.c) \ + $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*.c) \ + $(wildcard $(ESPCOMP)/lwip/lwip/src/netif/*/*/*.c) \ + $(wildcard $(ESPCOMP)/lwip/port/esp32/*.c) \ + $(wildcard $(ESPCOMP)/lwip/port/esp32/*/*.c) \ ) -ESPIDF_MBEDTLS_O = $(addprefix $(ESPCOMP)/mbedtls/,\ - mbedtls/library/entropy.o \ - mbedtls/library/pkcs12.o \ - mbedtls/library/ccm.o \ - mbedtls/library/pk.o \ - mbedtls/library/sha1.o \ - mbedtls/library/x509_csr.o \ - mbedtls/library/ssl_cli.o \ - mbedtls/library/ecp.o \ - mbedtls/library/blowfish.o \ - mbedtls/library/x509.o \ - mbedtls/library/ecp_curves.o \ - mbedtls/library/error.o \ - mbedtls/library/ssl_ticket.o \ - mbedtls/library/entropy_poll.o \ - mbedtls/library/cipher.o \ - mbedtls/library/version_features.o \ - mbedtls/library/ripemd160.o \ - mbedtls/library/rsa.o \ - mbedtls/library/rsa_internal.o \ - mbedtls/library/md.o \ - mbedtls/library/md_wrap.o \ - mbedtls/library/sha256.o \ - mbedtls/library/dhm.o \ - mbedtls/library/ssl_cache.o \ - mbedtls/library/pkwrite.o \ - mbedtls/library/base64.o \ - mbedtls/library/asn1parse.o \ - mbedtls/library/ssl_tls.o \ - mbedtls/library/hmac_drbg.o \ - mbedtls/library/pem.o \ - mbedtls/library/version.o \ - mbedtls/library/gcm.o \ - mbedtls/library/memory_buffer_alloc.o \ - mbedtls/library/md2.o \ - mbedtls/library/ecdsa.o \ - mbedtls/library/ssl_srv.o \ - mbedtls/library/x509_crt.o \ - mbedtls/library/ecdh.o \ - mbedtls/library/asn1write.o \ - mbedtls/library/md4.o \ - mbedtls/library/debug.o \ - mbedtls/library/x509_create.o \ - mbedtls/library/ecjpake.o \ - mbedtls/library/oid.o \ - mbedtls/library/md5.o \ - mbedtls/library/ssl_ciphersuites.o \ - mbedtls/library/sha512.o \ - mbedtls/library/xtea.o \ - mbedtls/library/aes.o \ - mbedtls/library/cipher_wrap.o \ - mbedtls/library/arc4.o \ - mbedtls/library/bignum.o \ - mbedtls/library/pkparse.o \ - mbedtls/library/padlock.o \ - mbedtls/library/threading.o \ - mbedtls/library/x509_crl.o \ - mbedtls/library/pkcs11.o \ - mbedtls/library/aesni.o \ - mbedtls/library/timing.o \ - mbedtls/library/certs.o \ - mbedtls/library/pkcs5.o \ - mbedtls/library/ssl_cookie.o \ - mbedtls/library/camellia.o \ - mbedtls/library/havege.o \ - mbedtls/library/des.o \ - mbedtls/library/x509write_csr.o \ - mbedtls/library/platform.o \ - mbedtls/library/platform_util.o \ - mbedtls/library/ctr_drbg.o \ - mbedtls/library/x509write_crt.o \ - mbedtls/library/pk_wrap.o \ - port/esp_bignum.o \ - port/esp_hardware.o \ - port/esp_mem.o \ - port/esp_sha1.o \ - port/esp_sha256.o \ - port/esp_sha512.o \ +ESPIDF_MBEDTLS_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/mbedtls/mbedtls/library/*.c) \ + $(wildcard $(ESPCOMP)/mbedtls/port/*.c) \ ) -$(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -D__ets__ -Wno-strict-aliasing -ESPIDF_WPA_SUPPLICANT_O = $(addprefix $(ESPCOMP)/wpa_supplicant/,\ - src/crypto/aes-internal-enc.o \ - src/crypto/sha256-internal.o \ - src/crypto/md5-internal.o \ - src/crypto/aes-internal.o \ - src/crypto/sha1.o \ - src/crypto/aes-internal-dec.o \ - src/crypto/aes-unwrap.o \ - src/crypto/crypto_internal-rsa.o \ - src/crypto/dh_groups.o \ - src/crypto/crypto_internal.o \ - src/crypto/aes-wrap.o \ - src/crypto/sha1-internal.o \ - src/crypto/dh_group5.o \ - src/crypto/sha256.o \ - src/crypto/rc4.o \ - src/crypto/md5.o \ - src/crypto/aes-cbc.o \ - src/crypto/sha1-pbkdf2.o \ - src/crypto/bignum.o \ - src/crypto/crypto_internal-modexp.o \ - src/crypto/crypto_internal-cipher.o \ - src/fast_crypto/fast_aes-unwrap.o \ - src/fast_crypto/fast_aes-wrap.o \ - src/fast_crypto/fast_sha256.o \ - src/fast_crypto/fast_sha256-internal.o \ - port/os_xtensa.o \ +$(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DALLOW_EVEN_MOD -D__ets__ -Wno-strict-aliasing +ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/wpa_supplicant/port/*.c) \ + $(wildcard $(ESPCOMP)/wpa_supplicant/src/*/*.c) \ ) -ESPIDF_SDMMC_O = $(addprefix $(ESPCOMP)/sdmmc/,\ - sdmmc_cmd.o \ - sdmmc_common.o \ - sdmmc_init.o \ - sdmmc_mmc.o \ - sdmmc_sd.o \ - sdmmc_io.o \ - ) +ESPIDF_SDMMC_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/sdmmc/*.c)) OBJ_ESPIDF = LIB_ESPIDF = @@ -697,7 +374,6 @@ $(eval $(call gen_espidf_lib_rule,heap,$(ESPIDF_HEAP_O))) $(eval $(call gen_espidf_lib_rule,soc,$(ESPIDF_SOC_O))) $(eval $(call gen_espidf_lib_rule,cxx,$(ESPIDF_CXX_O))) $(eval $(call gen_espidf_lib_rule,ethernet,$(ESPIDF_ETHERNET_O))) -$(eval $(call gen_espidf_lib_rule,expat,$(ESPIDF_EXPAT_O))) $(eval $(call gen_espidf_lib_rule,pthread,$(ESPIDF_PTHREAD_O))) $(eval $(call gen_espidf_lib_rule,freertos,$(ESPIDF_FREERTOS_O))) $(eval $(call gen_espidf_lib_rule,vfs,$(ESPIDF_VFS_O))) @@ -708,7 +384,6 @@ $(eval $(call gen_espidf_lib_rule,tcpip_adapter,$(ESPIDF_TCPIP_ADAPTER_O))) $(eval $(call gen_espidf_lib_rule,app_trace,$(ESPIDF_APP_TRACE_O))) $(eval $(call gen_espidf_lib_rule,app_update,$(ESPIDF_APP_UPDATE_O))) $(eval $(call gen_espidf_lib_rule,newlib,$(ESPIDF_NEWLIB_O))) -$(eval $(call gen_espidf_lib_rule,nghttp,$(ESPIDF_NGHTTP_O))) $(eval $(call gen_espidf_lib_rule,nvs_flash,$(ESPIDF_NVS_FLASH_O))) $(eval $(call gen_espidf_lib_rule,smartconfig_ack,$(ESPIDF_SMARTCONFIG_ACK_O))) $(eval $(call gen_espidf_lib_rule,spi_flash,$(ESPIDF_SPI_FLASH_O))) From 995f9cfdfcda96698c63de7a707981ef8bf2cecc Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Mon, 22 Jul 2019 22:59:55 +0300 Subject: [PATCH 0296/1299] esp32: Pin MicroPython tasks to a specific core. On this port the GIL is enabled and everything works under the assumption of the GIL, ie that a given task has exclusive access to the uPy state, and any ISRs interrupt the current task and therefore the ISR inherits exclusive access to the uPy state for the duration of its execution. If the MicroPython tasks are not pinned to a specific core then an ISR may be executed on a different core to the task, making it possible for the main task and an ISR to execute in parallel, breaking the assumption of the GIL. The easiest and safest fix for this is to pin all MicroPython related code to the same CPU core, as done by this patch. Then any ISR that accesses MicroPython state must be registered from a MicroPython task, to ensure it is invoked on the same core. See issue #4895. --- ports/esp32/main.c | 2 +- ports/esp32/mphalport.h | 3 +++ ports/esp32/mpthreadport.c | 5 ++--- ports/esp32/network_ppp.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ports/esp32/main.c b/ports/esp32/main.c index d4f79646f6c89..c8dde337c5d95 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -151,7 +151,7 @@ void mp_task(void *pvParameter) { void app_main(void) { nvs_flash_init(); - xTaskCreate(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle); + xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID); } void nlr_jump_fail(void *val) { diff --git a/ports/esp32/mphalport.h b/ports/esp32/mphalport.h index ff39b7aa1cbcc..575cdbe720d80 100644 --- a/ports/esp32/mphalport.h +++ b/ports/esp32/mphalport.h @@ -35,6 +35,9 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +// The core that the MicroPython task(s) are pinned to +#define MP_TASK_COREID (1) + extern TaskHandle_t mp_main_task_handle; extern ringbuf_t stdin_ringbuf; diff --git a/ports/esp32/mpthreadport.c b/ports/esp32/mpthreadport.c index 6c4ed9b5e357d..9557d4071454a 100644 --- a/ports/esp32/mpthreadport.c +++ b/ports/esp32/mpthreadport.c @@ -27,10 +27,9 @@ #include "stdio.h" -#include "py/mpconfig.h" -#include "py/mpstate.h" #include "py/gc.h" #include "py/mpthread.h" +#include "py/mphal.h" #include "mpthreadport.h" #include "esp_task.h" @@ -130,7 +129,7 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i mp_thread_mutex_lock(&thread_mutex, 1); // create thread - BaseType_t result = xTaskCreate(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, &th->id); + BaseType_t result = xTaskCreatePinnedToCore(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, &th->id, MP_TASK_COREID); if (result != pdPASS) { mp_thread_mutex_unlock(&thread_mutex); nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index 8065409158041..aca4bbc1e9b51 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -133,7 +133,7 @@ STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { ppp_set_usepeerdns(self->pcb, 1); pppapi_connect(self->pcb, 0); - xTaskCreate(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle); + xTaskCreatePinnedToCore(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle, MP_TASK_COREID); self->active = true; } else { if (!self->active) { From 4d94fae83322dd1b4197fd770fa9d0b7474ce72b Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Jul 2019 16:48:37 +1000 Subject: [PATCH 0297/1299] tools/pyboard.py: Add filesystem commands to ls/cat/cp/rm remote files. Use "-f" to select filesystem mode, followed by the command to execute. Optionally put ":" at the start of a filename to indicate that it's on the remote device, if it would otherwise be ambiguous. Examples: $ pyboard.py -f ls $ pyboard.py -f cat main.py $ pyboard.py -f cp :main.py . # get from device $ pyboard.py -f cp main.py : # put to device $ pyboard.py -f rm main.py --- tools/pyboard.py | 110 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 5 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index d906235066be5..c32fb002ca6ec 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -4,7 +4,7 @@ # # The MIT License (MIT) # -# Copyright (c) 2014-2016 Damien P. George +# Copyright (c) 2014-2019 Damien P. George # Copyright (c) 2017 Paul Sokolovsky # # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -363,8 +363,8 @@ def eval(self, expression): ret = ret.strip() return ret - def exec_(self, command): - ret, ret_err = self.exec_raw(command) + def exec_(self, command, data_consumer=None): + ret, ret_err = self.exec_raw(command, data_consumer=data_consumer) if ret_err: raise PyboardError('exception', ret, ret_err) return ret @@ -378,6 +378,52 @@ def get_time(self): t = str(self.eval('pyb.RTC().datetime()'), encoding='utf8')[1:-1].split(', ') return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6]) + def fs_ls(self, src): + cmd = "import uos\nfor f in uos.ilistdir(%s):\n" \ + " print('{:12} {}{}'.format(f[3]if len(f)>3 else 0,f[0],'/'if f[1]&0x4000 else ''))" % \ + (("'%s'" % src) if src else '') + self.exec_(cmd, data_consumer=stdout_write_bytes) + + def fs_cat(self, src, chunk_size=256): + cmd = "with open('%s') as f:\n while 1:\n" \ + " b=f.read(%u)\n if not b:break\n print(b,end='')" % (src, chunk_size) + self.exec_(cmd, data_consumer=stdout_write_bytes) + + def fs_get(self, src, dest, chunk_size=256): + self.exec_("f=open('%s','rb')\nr=f.read" % src) + with open(dest, 'wb') as f: + while True: + data = bytearray() + self.exec_("print(r(%u))" % chunk_size, data_consumer=lambda d:data.extend(d)) + assert data.endswith(b'\r\n\x04') + data = eval(str(data[:-3], 'ascii')) + if not data: + break + f.write(data) + self.exec_("f.close()") + + def fs_put(self, src, dest, chunk_size=256): + self.exec_("f=open('%s','wb')\nw=f.write" % dest) + with open(src, 'rb') as f: + while True: + data = f.read(chunk_size) + if not data: + break + if sys.version_info < (3,): + self.exec_('w(b' + repr(data) + ')') + else: + self.exec_('w(' + repr(data) + ')') + self.exec_("f.close()") + + def fs_mkdir(self, dir): + self.exec_("import uos\nuos.mkdir('%s')" % dir) + + def fs_rmdir(self, dir): + self.exec_("import uos\nuos.rmdir('%s')" % dir) + + def fs_rm(self, src): + self.exec_("import uos\nuos.remove('%s')" % src) + # in Python2 exec is a keyword so one must use "exec_" # but for Python3 we want to provide the nicer version "exec" setattr(Pyboard, "exec", Pyboard.exec_) @@ -390,6 +436,54 @@ def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', pas pyb.exit_raw_repl() pyb.close() +def filesystem_command(pyb, args): + def fname_remote(src): + if src.startswith(':'): + src = src[1:] + return src + def fname_cp_dest(src, dest): + src = src.rsplit('/', 1)[-1] + if dest is None or dest == '': + dest = src + elif dest == '.': + dest = './' + src + elif dest.endswith('/'): + dest += src + return dest + + cmd = args[0] + args = args[1:] + try: + if cmd == 'cp': + srcs = args[:-1] + dest = args[-1] + if srcs[0].startswith('./') or dest.startswith(':'): + op = pyb.fs_put + fmt = 'cp %s :%s' + dest = fname_remote(dest) + else: + op = pyb.fs_get + fmt = 'cp :%s %s' + for src in srcs: + src = fname_remote(src) + dest2 = fname_cp_dest(src, dest) + print(fmt % (src, dest2)) + op(src, dest2) + else: + op = {'ls': pyb.fs_ls, 'cat': pyb.fs_cat, 'mkdir': pyb.fs_mkdir, + 'rmdir': pyb.fs_rmdir, 'rm': pyb.fs_rm}[cmd] + if cmd == 'ls' and not args: + args = [''] + for src in args: + src = fname_remote(src) + print('%s :%s' % (cmd, src)) + op(src) + except PyboardError as er: + print(str(er.args[2], 'ascii')) + pyb.exit_raw_repl() + pyb.close() + sys.exit(1) + def main(): import argparse cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.') @@ -400,6 +494,7 @@ def main(): cmd_parser.add_argument('-c', '--command', help='program passed in as string') cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available') cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]') + cmd_parser.add_argument('-f', '--filesystem', action='store_true', help='perform a filesystem action') cmd_parser.add_argument('files', nargs='*', help='input files') args = cmd_parser.parse_args() @@ -411,7 +506,7 @@ def main(): sys.exit(1) # run any command or file(s) - if args.command is not None or len(args.files): + if args.command is not None or args.filesystem or len(args.files): # we must enter raw-REPL mode to execute commands # this will do a soft-reset of the board try: @@ -436,6 +531,11 @@ def execbuffer(buf): stdout_write_bytes(ret_err) sys.exit(1) + # do filesystem commands, if given + if args.filesystem: + filesystem_command(pyb, args.files) + args.files.clear() + # run the command, if given if args.command is not None: execbuffer(args.command.encode('utf-8')) @@ -450,7 +550,7 @@ def execbuffer(buf): pyb.exit_raw_repl() # if asked explicitly, or no files given, then follow the output - if args.follow or (args.command is None and len(args.files) == 0): + if args.follow or (args.command is None and not args.filesystem and len(args.files) == 0): try: ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes) except PyboardError as er: From 0da2f6f23a8316f6810c47b2d8410bf11029f2a1 Mon Sep 17 00:00:00 2001 From: badlyby Date: Fri, 19 Jul 2019 08:52:48 +0800 Subject: [PATCH 0298/1299] stm32/flashbdev: Support internal filesystem on STM32F722/23/32/33. --- ports/stm32/flash.c | 8 ++++++++ ports/stm32/flashbdev.c | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index 58cc012793b5d..49cbbe06aaa8e 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -62,11 +62,19 @@ static const flash_layout_t flash_layout[] = { // FLASH_FLAG_ERSERR (Erasing Sequence Error) in STM32F7 #define FLASH_FLAG_PGSERR FLASH_FLAG_ERSERR +#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) +static const flash_layout_t flash_layout[] = { + { 0x08000000, 0x04000, 4 }, + { 0x08010000, 0x10000, 1 }, + { 0x08020000, 0x20000, 3 }, +}; +#else static const flash_layout_t flash_layout[] = { { 0x08000000, 0x08000, 4 }, { 0x08020000, 0x20000, 1 }, { 0x08040000, 0x40000, 3 }, }; +#endif #elif defined(STM32L0) || defined(STM32L4) || defined(STM32WB) diff --git a/ports/stm32/flashbdev.c b/ports/stm32/flashbdev.c index 470f3d086061e..15bf0d6b0a837 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -86,6 +86,13 @@ STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k #define FLASH_MEM_SEG2_START_ADDR (0x08140000) // sector 18 #define FLASH_MEM_SEG2_NUM_BLOCKS (128) // sector 18: 64k(of 128k) +#elif defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) + +#define CACHE_MEM_START_ADDR (0x20000000) // DTCM data RAM, 64k +#define FLASH_SECTOR_SIZE_MAX (0x10000) // 64k max +#define FLASH_MEM_SEG1_START_ADDR (0x08004000) // sector 1 +#define FLASH_MEM_SEG1_NUM_BLOCKS (224) // sectors 1,2,3,4: 16k+16k+16k+64k=112k + #elif defined(STM32F746xx) || defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx) // The STM32F746 doesn't really have CCRAM, so we use the 64K DTCM for this. From 09267bb147c06ef5350b91034342924a9d9efa05 Mon Sep 17 00:00:00 2001 From: badlyby Date: Fri, 19 Jul 2019 08:58:02 +0800 Subject: [PATCH 0299/1299] stm32/boards/stm32f722.ld: Provide memory regions for internal FS. --- ports/stm32/boards/stm32f722.ld | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/stm32f722.ld b/ports/stm32/boards/stm32f722.ld index ab41f0ea90ee0..fe84a49637e51 100644 --- a/ports/stm32/boards/stm32f722.ld +++ b/ports/stm32/boards/stm32f722.ld @@ -6,9 +6,11 @@ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K - FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sectors 0,1 */ - FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 480K /* sectors 2-7 */ - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K /* DTCM+SRAM1+SRAM2 */ + FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0, 16K */ + FLASH_FS (r) : ORIGIN = 0x08004000, LENGTH = 112K /* sectors 1-4 3*16KiB 1*64KiB*/ + FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 384K /* sectors 5-7 3*128KiB = 384K */ + DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* Used for storage cache */ + RAM (xrw) : ORIGIN = 0x20010000, LENGTH = 192K /* SRAM1 = 176K, SRAM2 = 16K */ } /* produce a link error if there is not this amount of RAM for these sections */ From 3b258ef213d34b402c170fbb63dafbab53ea91b2 Mon Sep 17 00:00:00 2001 From: badlyby Date: Fri, 19 Jul 2019 21:44:16 +0800 Subject: [PATCH 0300/1299] stm32/boards/NUCLEO_F722ZE: Add definition files for new board. --- ports/stm32/boards/NUCLEO_F722ZE/board_init.c | 8 ++ .../boards/NUCLEO_F722ZE/mpconfigboard.h | 68 ++++++++++++ .../boards/NUCLEO_F722ZE/mpconfigboard.mk | 6 + ports/stm32/boards/NUCLEO_F722ZE/pins.csv | 104 ++++++++++++++++++ .../boards/NUCLEO_F722ZE/stm32f7xx_hal_conf.h | 18 +++ 5 files changed, 204 insertions(+) create mode 100644 ports/stm32/boards/NUCLEO_F722ZE/board_init.c create mode 100644 ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h create mode 100644 ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.mk create mode 100644 ports/stm32/boards/NUCLEO_F722ZE/pins.csv create mode 100644 ports/stm32/boards/NUCLEO_F722ZE/stm32f7xx_hal_conf.h diff --git a/ports/stm32/boards/NUCLEO_F722ZE/board_init.c b/ports/stm32/boards/NUCLEO_F722ZE/board_init.c new file mode 100644 index 0000000000000..5a7c6052af9bf --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F722ZE/board_init.c @@ -0,0 +1,8 @@ +#include "py/mphal.h" + +void board_early_init(void) { + // Turn off the USB switch + #define USB_PowerSwitchOn pin_G6 + mp_hal_pin_output(USB_PowerSwitchOn); + mp_hal_pin_low(USB_PowerSwitchOn); +} diff --git a/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h new file mode 100644 index 0000000000000..5a7f650067051 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.h @@ -0,0 +1,68 @@ +// This board is only confirmed to operate using DFU mode and openocd. +// DFU mode can be accessed by setting BOOT0 (see schematics) +// To use openocd run "OPENOCD_CONFIG=boards/openocd_stm32f7.cfg" in +// the make command. + +#define MICROPY_HW_BOARD_NAME "NUCLEO-F722ZE" +#define MICROPY_HW_MCU_NAME "STM32F722" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) + +#define MICROPY_BOARD_EARLY_INIT board_early_init +void board_early_init(void); + +// HSE is 8MHz, run SYSCLK at 216MHz +#define MICROPY_HW_CLK_PLLM (4) +#define MICROPY_HW_CLK_PLLN (216) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (9) +#define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_7) // 210-216 MHz needs 7 wait states + +// UART config +#define MICROPY_HW_UART2_TX (pin_D5) +#define MICROPY_HW_UART2_RX (pin_D6) +#define MICROPY_HW_UART2_RTS (pin_D4) +#define MICROPY_HW_UART2_CTS (pin_D3) +#define MICROPY_HW_UART3_TX (pin_D8) +#define MICROPY_HW_UART3_RX (pin_D9) +#define MICROPY_HW_UART6_TX (pin_G14) +#define MICROPY_HW_UART6_RX (pin_G9) +#define MICROPY_HW_UART_REPL PYB_UART_3 +#define MICROPY_HW_UART_REPL_BAUD 115200 + +// I2C buses +#define MICROPY_HW_I2C1_SCL (pin_B8) +#define MICROPY_HW_I2C1_SDA (pin_B9) + +// SPI buses +#define MICROPY_HW_SPI3_NSS (pin_A4) +#define MICROPY_HW_SPI3_SCK (pin_B3) +#define MICROPY_HW_SPI3_MISO (pin_B4) +#define MICROPY_HW_SPI3_MOSI (pin_B5) + +// CAN buses +#define MICROPY_HW_CAN1_TX (pin_B9) +#define MICROPY_HW_CAN1_RX (pin_B8) + +// USRSW is pulled low, and pressing the button makes the input go high +#define MICROPY_HW_USRSW_PIN (pin_C13) +#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING) +#define MICROPY_HW_USRSW_PRESSED (1) + +// LEDs +#define MICROPY_HW_LED1 (pin_B0) // green +#define MICROPY_HW_LED2 (pin_B7) // blue +#define MICROPY_HW_LED3 (pin_B14) // red +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// USB config (CN13 - USB OTG FS) +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) +#define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) diff --git a/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.mk new file mode 100644 index 0000000000000..667c8e55da98c --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F722ZE/mpconfigboard.mk @@ -0,0 +1,6 @@ +MCU_SERIES = f7 +CMSIS_MCU = STM32F722xx +AF_FILE = boards/stm32f722_af.csv +LD_FILES = boards/stm32f722.ld boards/common_ifs.ld +TEXT0_ADDR = 0x08000000 +TEXT1_ADDR = 0x08020000 diff --git a/ports/stm32/boards/NUCLEO_F722ZE/pins.csv b/ports/stm32/boards/NUCLEO_F722ZE/pins.csv new file mode 100644 index 0000000000000..228d83a026b51 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F722ZE/pins.csv @@ -0,0 +1,104 @@ +A0,PA3 +A1,PC0 +A2,PC3 +A3,PF3 +A4,PF5 +A5,PF10 +A6,PB1 +A7,PC2 +A8,PF4 +D0,PG9 +D1,PG14 +D2,PF15 +D3,PE13 +D4,PF14 +D5,PE11 +D6,PE9 +D7,PF13 +D8,PF12 +D9,PD15 +D10,PD14 +D11,PA7 +D12,PA6 +D13,PA5 +D14,PB9 +D15,PB8 +D16,PC6 +D17,PB15 +D18,PB13 +D19,PB12 +D20,PA15 +D21,PC7 +D22,PB5 +D23,PB3 +D24,PA4 +D25,PB4 +D26,PB6 +D27,PB2 +D28,PD13 +D29,PD12 +D30,PD11 +D31,PE2 +D32,PA0 +D33,PB0 +D34,PE0 +D35,PB11 +D36,PB10 +D37,PE15 +D38,PE14 +D39,PE12 +D40,PE10 +D41,PE7 +D42,PE8 +D43,PC8 +D44,PC9 +D45,PC10 +D46,PC11 +D47,PC12 +D48,PD2 +D49,PG2 +D50,PG3 +D51,PD7 +D52,PD6 +D53,PD5 +D54,PD4 +D55,PD3 +D56,PE2 +D57,PE4 +D58,PE5 +D59,PE6 +D60,PE3 +D61,PF8 +D62,PF7 +D63,PF9 +D64,PG1 +D65,PG0 +D66,PD1 +D67,PD0 +D68,PF0 +D69,PF1 +D70,PF2 +D71,PA7 +LED1,PB0 +LED2,PB7 +LED3,PB14 +SW,PC13 +SD_SW,PC13 +OTG_FS_POWER,PG6 +OTG_FS_OVER_CURRENT,PG7 +USB_VBUS,PA9 +USB_ID,PA10 +USB_DM,PA11 +USB_DP,PA12 +USB_POWER,PG6 +VCP_TX,PD8 +VCP_RX,PD9 +UART2_TX,PD5 +UART2_RX,PD6 +UART2_RTS,PD4 +UART2_CTS,PD3 +UART6_TX,PG14 +UART6_RX,PG9 +SPI_B_NSS,PA4 +SPI_B_SCK,PB3 +SPI_B_MOSI,PB5 diff --git a/ports/stm32/boards/NUCLEO_F722ZE/stm32f7xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F722ZE/stm32f7xx_hal_conf.h new file mode 100644 index 0000000000000..9355a3867de50 --- /dev/null +++ b/ports/stm32/boards/NUCLEO_F722ZE/stm32f7xx_hal_conf.h @@ -0,0 +1,18 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * MIT License; Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H + +#include "boards/stm32f7xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (8000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (5000) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H From e9593d50755cfdd157d1bd67a02a1314f9ccedb5 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sun, 21 Jul 2019 23:23:11 +0300 Subject: [PATCH 0301/1299] py/sequence: Fix grammar in comment about equality. --- py/sequence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/sequence.c b/py/sequence.c index c66fde98f64c8..4c19fc69ea3d5 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -165,7 +165,7 @@ bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte * size_t min_len = len1 < len2 ? len1 : len2; int res = memcmp(data1, data2, min_len); if (op == MP_BINARY_OP_EQUAL) { - // If we are checking for equality, here're the answer + // If we are checking for equality, here's the answer return res == 0; } if (res < 0) { From b1129df4780abc5f140b473d10ebe5316793aac2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 25 Jul 2019 15:16:57 +1000 Subject: [PATCH 0302/1299] stm32/dma: Fix re-start of DMA stream by clearing all event flags. As per the datasheet, all event flags for a stream must be cleared before enabling it. Fixes issue #4944 (with DAC.write_timed). --- ports/stm32/dma.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 8a3f743fe7157..3d275684d2c32 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -922,6 +922,30 @@ void dma_nohal_deinit(const dma_descr_t *descr) { } void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_addr, uint16_t len) { + // Must clear all event flags for this stream before enabling it + DMA_TypeDef *dma_ctrl; + uint32_t ch = descr->id; + if (ch < NSTREAMS_PER_CONTROLLER) { + dma_ctrl = DMA1; + } else { + dma_ctrl = DMA2; + ch -= NSTREAMS_PER_CONTROLLER; + } + __IO uint32_t *ifcr; + if (ch <= 3) { + ifcr = &dma_ctrl->LIFCR; + } else { + ifcr = &dma_ctrl->HIFCR; + ch -= 4; + } + if (ch <= 1) { + ch = ch * 6; + } else { + ch = 4 + ch * 6; + } + *ifcr = 0x3d << ch; + + // Configure and enable stream DMA_Stream_TypeDef *dma = descr->instance; dma->CR &= ~DMA_SxCR_DBM; dma->NDTR = len; From fa07deda9f129c1992726d2a51c6eaac168247f0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 25 Jul 2019 17:42:17 +1000 Subject: [PATCH 0303/1299] stm32/usbd_hid_interface: Rewrite USB HID interface code. The previous version did not work on MCUs that only had USB device mode (compared to OTG) because of the handling of NAK. And this previous handling of NAK had a race condition where a new packet could come in before USBD_HID_SetNAK was called (since USBD_HID_ReceivePacket clears NAK as part of its operation). Furthermore, the double buffering of incoming reports was not working, only one buffer could be used at a time. This commit rewrites the HID interface code to have a single incoming buffer, and only calls USBD_HID_ReceivePacket after the user has read the incoming report (similar to how the VCP does its flow control). As such, USBD_HID_SetNAK and USBD_HID_ClearNAK are no longer needed. API functionality from the user's point of view should be unchanged with this commit. --- ports/stm32/usb.c | 5 + ports/stm32/usbd_hid_interface.c | 127 ++++++------------ ports/stm32/usbd_hid_interface.h | 16 ++- .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 24 ---- 4 files changed, 57 insertions(+), 115 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 2d1f6084fe044..3308f07449833 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -787,6 +787,11 @@ STATIC mp_obj_t pyb_usb_hid_recv(size_t n_args, const mp_obj_t *args, mp_map_t * // receive the data int ret = usbd_hid_rx(&self->usb_dev->usbd_hid_itf, vstr.len, (uint8_t*)vstr.buf, vals[1].u_int); + if (ret < 0) { + // error, just return 0/empty bytes + ret = 0; + } + // return the received data if (o_ret != MP_OBJ_NULL) { return mp_obj_new_int(ret); // number of bytes read into given buffer diff --git a/ports/stm32/usbd_hid_interface.c b/ports/stm32/usbd_hid_interface.c index 033d83ea64843..386cf34d70bc3 100644 --- a/ports/stm32/usbd_hid_interface.c +++ b/ports/stm32/usbd_hid_interface.c @@ -1,113 +1,70 @@ /* * This file is part of the MicroPython project, http://micropython.org/ * - * Taken from ST Cube library and heavily modified. See below for original - * copyright header. + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. */ -/** - ****************************************************************************** - * @file USB_Device/CDC_Standalone/Src/usbd_cdc_interface.c - * @author MCD Application Team - * @version V1.0.1 - * @date 26-February-2014 - * @brief Source file for USBD CDC interface - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.st.com/software_license_agreement_liberty_v2 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ - -#include - #include "usbd_hid_interface.h" -#include "py/obj.h" -#include "irq.h" +#include "py/mperrno.h" +#include "py/mphal.h" #include "usb.h" #if MICROPY_HW_USB_HID uint8_t *usbd_hid_init(usbd_hid_state_t *hid_in) { usbd_hid_itf_t *hid = (usbd_hid_itf_t*)hid_in; - - hid->current_read_buffer = 0; - hid->last_read_len = 0; - hid->current_write_buffer = 0; - - // Return the buffer to place the first USB OUT packet - return hid->buffer[hid->current_write_buffer]; + hid->report_in_len = USBD_HID_REPORT_INVALID; + return &hid->report_in_buf[0]; // location to place first incoming report } -// Data received over USB OUT endpoint is processed here. -// len: number of bytes received into the buffer we passed to USBD_HID_ReceivePacket -// Returns USBD_OK if all operations are OK else USBD_FAIL int8_t usbd_hid_receive(usbd_hid_state_t *hid_in, size_t len) { + // Incoming report: save the length but don't schedule next report until user reads this one usbd_hid_itf_t *hid = (usbd_hid_itf_t*)hid_in; - - hid->current_write_buffer = !hid->current_write_buffer; - hid->last_read_len = len; - // initiate next USB packet transfer, to append to existing data in buffer - USBD_HID_ReceivePacket(&hid->base, hid->buffer[hid->current_write_buffer]); - // Set NAK to indicate we need to process read buffer - USBD_HID_SetNAK(&hid->base); + hid->report_in_len = len; return USBD_OK; } -// Returns number of ready rx buffers. -int usbd_hid_rx_num(usbd_hid_itf_t *hid) { - return hid->current_read_buffer != hid->current_write_buffer; -} - -// timout in milliseconds. -// Returns number of bytes read from the device. -int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout) { - // Wait until we have buffer to read - uint32_t start = HAL_GetTick(); - while (hid->current_read_buffer == hid->current_write_buffer) { - // Wraparound of tick is taken care of by 2's complement arithmetic. - if (HAL_GetTick() - start >= timeout) { - // timeout - return 0; +int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_ms) { + // Wait for an incoming report + uint32_t t0 = mp_hal_ticks_ms(); + while (hid->report_in_len == USBD_HID_REPORT_INVALID) { + if (mp_hal_ticks_ms() - t0 >= timeout_ms || query_irq() == IRQ_STATE_DISABLED) { + return -MP_ETIMEDOUT; } - if (query_irq() == IRQ_STATE_DISABLED) { - // IRQs disabled so buffer will never be filled; return immediately - return 0; - } - __WFI(); // enter sleep mode, waiting for interrupt - } - - // There is not enough space in buffer - if (len < hid->last_read_len) { - return 0; + MICROPY_EVENT_POLL_HOOK } - // Copy bytes from device to user buffer - int read_len = hid->last_read_len; - memcpy(buf, hid->buffer[hid->current_read_buffer], read_len); - hid->current_read_buffer = !hid->current_read_buffer; + // Copy bytes from report to user buffer + int n = MIN(len, hid->report_in_len); + memcpy(buf, &hid->report_in_buf[0], n); - // Clear NAK to indicate we are ready to read more data - USBD_HID_ClearNAK(&hid->base); + // Schedule to receive next incoming report + hid->report_in_len = USBD_HID_REPORT_INVALID; + USBD_HID_ReceivePacket(&hid->base, &hid->report_in_buf[0]); - // Success, return number of bytes read - return read_len; + // Return number of bytes read into user buffer + return n; } #endif // MICROPY_HW_USB_HID diff --git a/ports/stm32/usbd_hid_interface.h b/ports/stm32/usbd_hid_interface.h index 777fa93403052..5d2c9ad870f15 100644 --- a/ports/stm32/usbd_hid_interface.h +++ b/ports/stm32/usbd_hid_interface.h @@ -4,18 +4,22 @@ #ifndef MICROPY_INCLUDED_STM32_USBD_HID_INTERFACE_H #define MICROPY_INCLUDED_STM32_USBD_HID_INTERFACE_H +#include #include "usbd_cdc_msc_hid.h" +#define USBD_HID_REPORT_INVALID ((size_t)-1) + typedef struct _usbd_hid_itf_t { usbd_hid_state_t base; // state for the base HID layer - uint8_t buffer[2][HID_DATA_FS_MAX_PACKET_SIZE]; // pair of buffers to read individual packets into - int8_t current_read_buffer; // which buffer to read from - uint32_t last_read_len; // length of last read - int8_t current_write_buffer; // which buffer to write to + volatile size_t report_in_len; + uint8_t report_in_buf[HID_DATA_FS_MAX_PACKET_SIZE]; } usbd_hid_itf_t; -int usbd_hid_rx_num(usbd_hid_itf_t *hid); -int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout); +static inline int usbd_hid_rx_num(usbd_hid_itf_t *hid) { + return hid->report_in_len != USBD_HID_REPORT_INVALID; +} + +int usbd_hid_rx(usbd_hid_itf_t *hid, size_t len, uint8_t *buf, uint32_t timeout_ms); #endif // MICROPY_INCLUDED_STM32_USBD_HID_INTERFACE_H diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 32ce4ca8755ea..e13a93ddbc9e1 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -1190,30 +1190,6 @@ uint8_t USBD_HID_SendReport(usbd_hid_state_t *hid, uint8_t *report, uint16_t len return USBD_FAIL; } -uint8_t USBD_HID_SetNAK(usbd_hid_state_t *hid) { - // get USBx object from pdev (needed for USBx_OUTEP macro below) - PCD_HandleTypeDef *hpcd = hid->usbd->pdev->pData; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - #if defined(STM32H7) - uint32_t USBx_BASE = (uint32_t)USBx; - #endif - // set NAK on HID OUT endpoint - USBx_OUTEP(HID_OUT_EP_WITH_CDC)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - return USBD_OK; -} - -uint8_t USBD_HID_ClearNAK(usbd_hid_state_t *hid) { - // get USBx object from pdev (needed for USBx_OUTEP macro below) - PCD_HandleTypeDef *hpcd = hid->usbd->pdev->pData; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - #if defined(STM32H7) - uint32_t USBx_BASE = (uint32_t)USBx; - #endif - // clear NAK on HID OUT endpoint - USBx_OUTEP(HID_OUT_EP_WITH_CDC)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; - return USBD_OK; -} - #endif // CDC/MSC/HID interface class callback structure From ad0b7cb017acf8f26db8ca630013abbff61abc75 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 25 Jul 2019 17:49:53 +1000 Subject: [PATCH 0304/1299] stm32/boards/xxx_WB55: Enable USB HID now that it works on WB MCUs. --- ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h | 1 - ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h | 1 - 2 files changed, 2 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h index fc047880d1a20..beca2165696ab 100644 --- a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h @@ -59,6 +59,5 @@ // USB config #define MICROPY_HW_USB_FS (1) -#define MICROPY_HW_USB_HID (0) #define USBD_CDC_RX_DATA_SIZE (512) #define USBD_CDC_TX_DATA_SIZE (512) diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h index 77e2d4f3299a7..eebf30f628d21 100644 --- a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h @@ -38,6 +38,5 @@ // USB config #define MICROPY_HW_USB_FS (1) -#define MICROPY_HW_USB_HID (0) #define USBD_CDC_RX_DATA_SIZE (512) #define USBD_CDC_TX_DATA_SIZE (512) From 473157eeb9f88b3d62a963af087014920a47d624 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 26 Jul 2019 12:44:14 +1000 Subject: [PATCH 0305/1299] stm32/usbd_hid_interface: Include extra header to build with threading. --- ports/stm32/usbd_hid_interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/usbd_hid_interface.c b/ports/stm32/usbd_hid_interface.c index 386cf34d70bc3..8dc39f53d8240 100644 --- a/ports/stm32/usbd_hid_interface.c +++ b/ports/stm32/usbd_hid_interface.c @@ -26,6 +26,7 @@ #include "usbd_hid_interface.h" +#include "py/mpstate.h" #include "py/mperrno.h" #include "py/mphal.h" #include "usb.h" From 8f55a8fab625d645b189c471f3a32c0de7e5ef7d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 26 Jul 2019 12:44:47 +1000 Subject: [PATCH 0306/1299] travis: Build an stm32 board with threading enabled to test it with CI. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1229e6e689c57..e319f095b13eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,7 @@ jobs: - make ${MAKEOPTS} -C ports/stm32 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 - - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32F769DISC + - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32F769DISC CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32L476DISC - make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBD_SF6 From 01054f20925b92229402750979864f8d38a76916 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 16 Jul 2019 14:29:22 -0700 Subject: [PATCH 0307/1299] py/objdict: Quote non-string types when used as keys in JSON output. JSON requires that keys of objects be strings. CPython will therefore automatically quote simple types (NoneType, bool, int, float) when they are used directly as keys in JSON output. To prevent subtle bugs and emit compliant JSON, MicroPython should at least test for such keys so they aren't silently let through. Then doing the actual quoting is a similar cost to raising an exception, so that's what is implemented by this patch. Fixes issue #4790. --- py/objdict.c | 8 ++++++++ tests/extmod/ujson_dumps.py | 4 ++++ tests/extmod/ujson_dumps_float.py | 1 + 3 files changed, 13 insertions(+) diff --git a/py/objdict.c b/py/objdict.c index 0a223f7314c97..02a2346fdec1d 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -31,6 +31,7 @@ #include "py/runtime.h" #include "py/builtin.h" #include "py/objtype.h" +#include "py/objstr.h" #define mp_obj_is_dict_type(o) (mp_obj_is_obj(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->make_new == dict_make_new) @@ -70,7 +71,14 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ mp_print_str(print, ", "); } first = false; + bool add_quote = MICROPY_PY_UJSON && kind == PRINT_JSON && !mp_obj_is_str_or_bytes(next->key); + if (add_quote) { + mp_print_str(print, "\""); + } mp_obj_print_helper(print, next->key, kind); + if (add_quote) { + mp_print_str(print, "\""); + } mp_print_str(print, ": "); mp_obj_print_helper(print, next->value, kind); } diff --git a/tests/extmod/ujson_dumps.py b/tests/extmod/ujson_dumps.py index d732718019ee2..c33126cec6465 100644 --- a/tests/extmod/ujson_dumps.py +++ b/tests/extmod/ujson_dumps.py @@ -26,3 +26,7 @@ print(json.dumps({"a":(2,[3,None])})) print(json.dumps('"quoted"')) print(json.dumps('space\n\r\tspace')) +print(json.dumps({None: -1})) +print(json.dumps({False: 0})) +print(json.dumps({True: 1})) +print(json.dumps({1: 2})) diff --git a/tests/extmod/ujson_dumps_float.py b/tests/extmod/ujson_dumps_float.py index e8cceb6f1a533..40adb1e267548 100644 --- a/tests/extmod/ujson_dumps_float.py +++ b/tests/extmod/ujson_dumps_float.py @@ -8,3 +8,4 @@ raise SystemExit print(json.dumps(1.2)) +print(json.dumps({1.5: 'hi'})) From 7c15e50eb880f7246fca3fdd11c967b151117ddf Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 30 Jul 2019 17:31:23 +1000 Subject: [PATCH 0308/1299] esp32/Makefile: Include CFLAGS_EXTRA in CFLAGS definition. Following other ports, so builds can be customised more easily, eg on the command line building with a user C-module. --- ports/esp32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index cb8c88a2d794d..c6ef04b465225 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -126,7 +126,7 @@ CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfie CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) CFLAGS += -DIDF_VER=\"$(IDF_VER)\" -CFLAGS += $(CFLAGS_MOD) +CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) # this is what ESPIDF uses for c++ compilation CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP) From a8e3201b376d931a77e66dc80293c570983f9c7b Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Mon, 8 Jul 2019 11:26:20 +0200 Subject: [PATCH 0309/1299] py/builtinimport: Populate __file__ when importing frozen or mpy files. Note that bytecode already includes the source filename as a qstr so there is no additional memory used by the interning operation here. --- py/builtinimport.c | 12 ++++++------ tests/unix/extra_coverage.py | 6 ++++-- tests/unix/extra_coverage.py.exp | 6 ++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/py/builtinimport.c b/py/builtinimport.c index 1a333b5404c03..008a21dcff5e2 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -145,11 +145,11 @@ STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex) { #endif #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_MODULE_FROZEN_MPY -STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) { +STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code, const char* source_name) { + (void)source_name; + #if MICROPY_PY___FILE__ - // TODO - //qstr source_name = lex->source_name; - //mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); + mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(qstr_from_str(source_name))); #endif // execute the module in its context @@ -206,7 +206,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) { // its data) in the list of frozen files, execute it. #if MICROPY_MODULE_FROZEN_MPY if (frozen_type == MP_FROZEN_MPY) { - do_execute_raw_code(module_obj, modref); + do_execute_raw_code(module_obj, modref, file_str); return; } #endif @@ -216,7 +216,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) { #if MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD if (file_str[file->len - 3] == 'm') { mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str); - do_execute_raw_code(module_obj, raw_code); + do_execute_raw_code(module_obj, raw_code, file_str); return; } #endif diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index 13721f1f479c3..cb68bae4d9dd1 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -48,13 +48,15 @@ # test basic import of frozen scripts import frzstr1 +print(frzstr1.__file__) import frzmpy1 +print(frzmpy1.__file__) # test import of frozen packages with __init__.py import frzstr_pkg1 -print(frzstr_pkg1.x) +print(frzstr_pkg1.__file__, frzstr_pkg1.x) import frzmpy_pkg1 -print(frzmpy_pkg1.x) +print(frzmpy_pkg1.__file__, frzmpy_pkg1.x) # test import of frozen packages without __init__.py from frzstr_pkg2.mod import Foo diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 6c483f7e547c5..a9889c0e9530b 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -94,11 +94,13 @@ OSError None None frzstr1 +frzstr1.py frzmpy1 +frzmpy1.py frzstr_pkg1.__init__ -1 +frzstr_pkg1/__init__.py 1 frzmpy_pkg1.__init__ -1 +frzmpy_pkg1/__init__.py 1 frzstr_pkg2.mod 1 frzmpy_pkg2.mod From 60f1063797716cfec14c84afafec69bf06127777 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Fri, 19 Jul 2019 00:54:12 +0200 Subject: [PATCH 0310/1299] py/runtime: Allow to override builtins.__import__ with Python func. This patch adds a simple but powerful hook into the import system, in a CPython compatible way, by allowing to override builtins.__import__. This does introduce some overhead to all imports but it's minor: - the dict lookup of __import__ is bypassed if there are no modifications to the builtins module (which is the case at start up); - imports are not performance critical, usually done just at the start of a script; - compared to how much work is done in an import, looking up a value in a dict is a relatively small additional piece of work. --- py/runtime.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/py/runtime.c b/py/runtime.c index e502566059c02..70d7957198ea7 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1335,7 +1335,17 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) { args[3] = fromlist; args[4] = level; - // TODO lookup __import__ and call that instead of going straight to builtin implementation + #if MICROPY_CAN_OVERRIDE_BUILTINS + // Lookup __import__ and call that if it exists + mp_obj_dict_t *bo_dict = MP_STATE_VM(mp_module_builtins_override_dict); + if (bo_dict != NULL) { + mp_map_elem_t *import = mp_map_lookup(&bo_dict->map, MP_OBJ_NEW_QSTR(MP_QSTR___import__), MP_MAP_LOOKUP); + if (import != NULL) { + return mp_call_function_n_kw(import->value, 5, 0, args); + } + } + #endif + return mp_builtin___import__(5, args); } From f60229e261e61b59d563023b2df7204c4e01c51c Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Fri, 19 Jul 2019 00:56:40 +0200 Subject: [PATCH 0311/1299] py/modio: Call mp_import_name to do resource stream import. So code is not duplicated and it can take advantage of __import__ being overridden. --- py/modio.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/py/modio.c b/py/modio.c index 0f4a4326ca257..94ef5d42e2620 100644 --- a/py/modio.c +++ b/py/modio.c @@ -208,15 +208,8 @@ STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) { // package parameter being None, the path_in is interpreted as a // raw path. if (package_in != mp_const_none) { - mp_obj_t args[5]; - args[0] = package_in; - args[1] = mp_const_none; // TODO should be globals - args[2] = mp_const_none; // TODO should be locals - args[3] = mp_const_true; // Pass sentinel "non empty" value to force returning of leaf module - args[4] = MP_OBJ_NEW_SMALL_INT(0); - - // TODO lookup __import__ and call that instead of going straight to builtin implementation - mp_obj_t pkg = mp_builtin___import__(5, args); + // Pass "True" as sentinel value in fromlist to force returning of leaf module + mp_obj_t pkg = mp_import_name(mp_obj_str_get_qstr(package_in), mp_const_true, MP_OBJ_NEW_SMALL_INT(0)); mp_obj_t dest[2]; mp_load_method_maybe(pkg, MP_QSTR___path__, dest); From 48f43b77aa62b99147d52b794da26621bbd74ee8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 31 Jul 2019 22:34:43 +1000 Subject: [PATCH 0312/1299] tests: Add tests for overriding builtins.__import__. --- tests/basics/builtin_override.py | 18 ++++++++++++++++++ tests/import/import_override.py | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/import/import_override.py diff --git a/tests/basics/builtin_override.py b/tests/basics/builtin_override.py index 9f91341edd8ad..e3cf9165fcb2d 100644 --- a/tests/basics/builtin_override.py +++ b/tests/basics/builtin_override.py @@ -12,7 +12,25 @@ print(abs(1)) # __build_class__ is handled in a special way +orig_build_class = __build_class__ builtins.__build_class__ = lambda x, y: ('class', y) class A: pass print(A) +builtins.__build_class__ = orig_build_class + +# __import__ is handled in a special way +def custom_import(name, globals, locals, fromlist, level): + print('import', name, fromlist, level) + class M: + a = 1 + b = 2 + return M +builtins.__import__ = custom_import +__import__('A', None, None, None, 0) +import a +import a.b +from a import a +from a.b import a, b +from .a import a +from ..a import a, b diff --git a/tests/import/import_override.py b/tests/import/import_override.py new file mode 100644 index 0000000000000..6fe99009ee140 --- /dev/null +++ b/tests/import/import_override.py @@ -0,0 +1,17 @@ +# test overriding __import__ combined with importing from the filesystem + +def custom_import(name, globals, locals, fromlist, level): + print('import', name, fromlist, level) + class M: + var = 456 + return M + +orig_import = __import__ +try: + __import__("builtins").__import__ = custom_import +except AttributeError: + print("SKIP") + raise SystemExit + +# import1a will be done via normal import which will import1b via our custom import +orig_import('import1a') From 00e7fe8ab109a21e62ce367ebd9cc6a5dfb48803 Mon Sep 17 00:00:00 2001 From: Arsenijs Date: Tue, 30 Jul 2019 01:42:33 +0300 Subject: [PATCH 0313/1299] docs/library/framebuf: Add missing module reference in example code. --- docs/library/framebuf.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index ed4b78ab14625..b6d7dba5de247 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -19,7 +19,7 @@ For example:: import framebuf # FrameBuffer needs 2 bytes for every RGB565 pixel - fbuf = FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565) + fbuf = framebuf.FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565) fbuf.fill(0) fbuf.text('MicroPython!', 0, 0, 0xffff) From 80f5cef8d4937d1312a823a2a42c46b5140e5595 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 24 Jul 2019 17:05:02 +1000 Subject: [PATCH 0314/1299] extmod/modlwip: Implement raw sockets for lwIP. Configurable via MICROPY_PY_LWIP_SOCK_RAW. --- extmod/modlwip.c | 124 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 23 deletions(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index be932b6a9d276..050937750aaca 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -40,7 +40,7 @@ #include "lwip/init.h" #include "lwip/tcp.h" #include "lwip/udp.h" -//#include "lwip/raw.h" +#include "lwip/raw.h" #include "lwip/dns.h" #include "lwip/igmp.h" #if LWIP_VERSION_MAJOR < 2 @@ -280,6 +280,7 @@ typedef struct _lwip_socket_obj_t { volatile union { struct tcp_pcb *tcp; struct udp_pcb *udp; + struct raw_pcb *raw; } pcb; volatile union { struct pbuf *pbuf; @@ -361,6 +362,26 @@ static inline void exec_user_callback(lwip_socket_obj_t *socket) { } } +#if MICROPY_PY_LWIP_SOCK_RAW +// Callback for incoming raw packets. +#if LWIP_VERSION_MAJOR < 2 +STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr) +#else +STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) +#endif +{ + lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; + + if (socket->incoming.pbuf != NULL) { + pbuf_free(p); + } else { + socket->incoming.pbuf = p; + memcpy(&socket->peer, addr, sizeof(socket->peer)); + } + return 1; // we ate the packet +} +#endif + // Callback for incoming UDP packets. We simply stash the packet and the source address, // in case we need it for recvfrom. #if LWIP_VERSION_MAJOR < 2 @@ -515,8 +536,8 @@ STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err // Functions for socket send/receive operations. Socket send/recv and friends call // these to do the work. -// Helper function for send/sendto to handle UDP packets. -STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { +// Helper function for send/sendto to handle raw/UDP packets. +STATIC mp_uint_t lwip_raw_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { if (len > 0xffff) { // Any packet that big is probably going to fail the pbuf_alloc anyway, but may as well try len = 0xffff; @@ -536,11 +557,25 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui err_t err; if (ip == NULL) { - err = udp_send(socket->pcb.udp, p); + #if MICROPY_PY_LWIP_SOCK_RAW + if (socket->type == MOD_NETWORK_SOCK_RAW) { + err = raw_send(socket->pcb.raw, p); + } else + #endif + { + err = udp_send(socket->pcb.udp, p); + } } else { ip_addr_t dest; IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]); - err = udp_sendto(socket->pcb.udp, p, &dest, port); + #if MICROPY_PY_LWIP_SOCK_RAW + if (socket->type == MOD_NETWORK_SOCK_RAW) { + err = raw_sendto(socket->pcb.raw, p, &dest); + } else + #endif + { + err = udp_sendto(socket->pcb.udp, p, &dest, port); + } } pbuf_free(p); @@ -558,8 +593,8 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui return len; } -// Helper function for recv/recvfrom to handle UDP packets -STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { +// Helper function for recv/recvfrom to handle raw/UDP packets +STATIC mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { if (socket->incoming.pbuf == NULL) { if (socket->timeout != -1) { @@ -795,7 +830,13 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s socket->pcb.udp = udp_new(); socket->incoming.pbuf = NULL; break; - //case MOD_NETWORK_SOCK_RAW: socket->pcb.raw = raw_new(); break; + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: { + mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int(args[2]); + socket->pcb.raw = raw_new(proto); + break; + } + #endif default: mp_raise_OSError(MP_EINVAL); } @@ -817,6 +858,14 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void*)socket); break; } + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: { + // Register our receive callback now. Since raw sockets don't require binding or connection + // before use, there's no other good time to do it. + raw_recv(socket->pcb.raw, _lwip_raw_incoming, (void*)socket); + break; + } + #endif } socket->timeout = -1; @@ -1045,6 +1094,12 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { err = udp_connect(socket->pcb.udp, &dest, port); break; } + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: { + err = raw_connect(socket->pcb.raw, &dest); + break; + } + #endif } if (err != ERR_OK) { @@ -1079,10 +1134,12 @@ STATIC mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) { ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno); break; } - case MOD_NETWORK_SOCK_DGRAM: { - ret = lwip_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno); + case MOD_NETWORK_SOCK_DGRAM: + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: + #endif + ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno); break; - } } if (ret == -1) { mp_raise_OSError(_errno); @@ -1108,10 +1165,12 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) { ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno); break; } - case MOD_NETWORK_SOCK_DGRAM: { - ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, NULL, NULL, &_errno); + case MOD_NETWORK_SOCK_DGRAM: + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: + #endif + ret = lwip_raw_udp_receive(socket, (byte*)vstr.buf, len, NULL, NULL, &_errno); break; - } } if (ret == -1) { mp_raise_OSError(_errno); @@ -1143,10 +1202,12 @@ STATIC mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno); break; } - case MOD_NETWORK_SOCK_DGRAM: { - ret = lwip_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno); + case MOD_NETWORK_SOCK_DGRAM: + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: + #endif + ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno); break; - } } if (ret == -1) { mp_raise_OSError(_errno); @@ -1176,10 +1237,12 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno); break; } - case MOD_NETWORK_SOCK_DGRAM: { - ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, ip, &port, &_errno); + case MOD_NETWORK_SOCK_DGRAM: + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: + #endif + ret = lwip_raw_udp_receive(socket, (byte*)vstr.buf, len, ip, &port, &_errno); break; - } } if (ret == -1) { mp_raise_OSError(_errno); @@ -1331,7 +1394,10 @@ STATIC mp_uint_t lwip_socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, i case MOD_NETWORK_SOCK_STREAM: return lwip_tcp_receive(socket, buf, size, errcode); case MOD_NETWORK_SOCK_DGRAM: - return lwip_udp_receive(socket, buf, size, NULL, NULL, errcode); + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: + #endif + return lwip_raw_udp_receive(socket, buf, size, NULL, NULL, errcode); } // Unreachable return MP_STREAM_ERROR; @@ -1344,7 +1410,10 @@ STATIC mp_uint_t lwip_socket_write(mp_obj_t self_in, const void *buf, mp_uint_t case MOD_NETWORK_SOCK_STREAM: return lwip_tcp_send(socket, buf, size, errcode); case MOD_NETWORK_SOCK_DGRAM: - return lwip_udp_send(socket, buf, size, NULL, 0, errcode); + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: + #endif + return lwip_raw_udp_send(socket, buf, size, NULL, 0, errcode); } // Unreachable return MP_STREAM_ERROR; @@ -1385,6 +1454,11 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ if (socket->type == MOD_NETWORK_SOCK_DGRAM && socket->pcb.udp != NULL) { // UDP socket is writable ret |= MP_STREAM_POLL_WR; + #if MICROPY_PY_LWIP_SOCK_RAW + } else if (socket->type == MOD_NETWORK_SOCK_RAW && socket->pcb.raw != NULL) { + // raw socket is writable + ret |= MP_STREAM_POLL_WR; + #endif } else if (socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) { // TCP socket is writable // Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf @@ -1438,7 +1512,9 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ break; } case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break; - //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; + #if MICROPY_PY_LWIP_SOCK_RAW + case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; + #endif } socket->pcb.tcp = NULL; @@ -1660,7 +1736,9 @@ STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) }, { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) }, + #if MICROPY_PY_LWIP_SOCK_RAW { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) }, + #endif { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SOF_REUSEADDR) }, From 0e2b224b078d94e6ff2e346e3390572c1d24a4ec Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 25 Jul 2019 00:03:40 +1000 Subject: [PATCH 0315/1299] stm32/lwip_inc: Enable raw socket type. --- ports/stm32/lwip_inc/lwipopts.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/lwip_inc/lwipopts.h b/ports/stm32/lwip_inc/lwipopts.h index 8f54c83112bfc..c9bbde92f723b 100644 --- a/ports/stm32/lwip_inc/lwipopts.h +++ b/ports/stm32/lwip_inc/lwipopts.h @@ -17,6 +17,7 @@ #define LWIP_ARP 1 #define LWIP_ETHERNET 1 +#define LWIP_RAW 1 #define LWIP_NETCONN 0 #define LWIP_SOCKET 0 #define LWIP_STATS 0 From 102815f700fbc07fe58474570af933bc284a3fc5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 30 Jul 2019 22:58:41 +1000 Subject: [PATCH 0316/1299] stm32/mpconfigport.h: Enable lwIP raw sockets. --- ports/stm32/mpconfigport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 3e615c343731b..dbb6fa2d50670 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -150,6 +150,7 @@ #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_OS_DUPTERM (3) #define MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM (1) +#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new From 2d3d4f74830eddaba8e13ca9a860a5cb7fb2f163 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 30 Jul 2019 22:58:54 +1000 Subject: [PATCH 0317/1299] esp8266/mpconfigport.h: Enable lwIP raw sockets. --- ports/esp8266/mpconfigport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 3bf8220282945..5a1ca098d8504 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -81,6 +81,7 @@ #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_LWIP (1) +#define MICROPY_PY_LWIP_SOCK_RAW (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_PULSE (1) From cd35dd9d9a29836906acdce60c931f6352b536d0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 5 Aug 2019 16:32:10 +1000 Subject: [PATCH 0318/1299] py: Allow to pass in read-only buffers to viper and inline-asm funcs. Fixes #4936. --- py/nativeglue.c | 2 +- py/objfun.c | 2 +- tests/inlineasm/asmsum.py | 4 ++++ tests/inlineasm/asmsum.py.exp | 1 + tests/micropython/viper_addr.py | 10 ++++++++++ tests/micropython/viper_addr.py.exp | 1 + 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/py/nativeglue.c b/py/nativeglue.c index 979265a870a45..eb02907bdd435 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -65,7 +65,7 @@ mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type) { case MP_NATIVE_TYPE_UINT: return mp_obj_get_int_truncated(obj); default: { // cast obj to a pointer mp_buffer_info_t bufinfo; - if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_RW)) { + if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_READ)) { return (mp_uint_t)bufinfo.buf; } else { // assume obj is an integer that represents an address diff --git a/py/objfun.c b/py/objfun.c index d96c79ede4998..e0c6fb9271276 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -472,7 +472,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { return (mp_uint_t)items; } else { mp_buffer_info_t bufinfo; - if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_WRITE)) { + if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_READ)) { // supports the buffer protocol, return a pointer to the data return (mp_uint_t)bufinfo.buf; } else { diff --git a/tests/inlineasm/asmsum.py b/tests/inlineasm/asmsum.py index 07e71c7384927..9cbd8418eab54 100644 --- a/tests/inlineasm/asmsum.py +++ b/tests/inlineasm/asmsum.py @@ -55,3 +55,7 @@ def asm_sum_bytes(r0, r1): b = array.array('b', (10, 20, 30, 40, 50, 60, 70, 80)) n = asm_sum_bytes(len(b), b) print(b, n) + +b = b'\x01\x02\x03\x04' +n = asm_sum_bytes(len(b), b) +print(b, n) diff --git a/tests/inlineasm/asmsum.py.exp b/tests/inlineasm/asmsum.py.exp index d50a94c8db622..3c83da367ae7b 100644 --- a/tests/inlineasm/asmsum.py.exp +++ b/tests/inlineasm/asmsum.py.exp @@ -1,2 +1,3 @@ array('l', [100, 200, 300, 400]) 1000 array('b', [10, 20, 30, 40, 50, 60, 70, 80]) 360 +b'\x01\x02\x03\x04' 10 diff --git a/tests/micropython/viper_addr.py b/tests/micropython/viper_addr.py index cd953ce07d02d..0d8efb90b6db7 100644 --- a/tests/micropython/viper_addr.py +++ b/tests/micropython/viper_addr.py @@ -9,6 +9,13 @@ def memset(dest:ptr8, c:int, n:int): for i in range(n): dest[i] = c +@micropython.viper +def memsum(src:ptr8, n:int) -> int: + s = 0 + for i in range(n): + s += src[i] + return s + # create array and get its address ar = bytearray('0000') addr = get_addr(ar) @@ -27,3 +34,6 @@ def memset(dest:ptr8, c:int, n:int): # pass direct pointer to array buffer, with offset memset(addr + 2, ord('3'), len(ar) - 2) print(ar) + +# pass a read-only bytes object in +print(memsum(b'\x01\x02\x03\x04', 4)) diff --git a/tests/micropython/viper_addr.py.exp b/tests/micropython/viper_addr.py.exp index 87a18e1e2a067..8e08db9a54db9 100644 --- a/tests/micropython/viper_addr.py.exp +++ b/tests/micropython/viper_addr.py.exp @@ -4,3 +4,4 @@ bytearray(b'0000') bytearray(b'1111') bytearray(b'2222') bytearray(b'2233') +10 From efdcd6baa710af11bdc2f4930e42e439cc1b2ff8 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 5 Aug 2019 17:06:22 +0200 Subject: [PATCH 0319/1299] py/showbc: Fix off-by-one when showing address of unknown opcode. --- py/showbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/showbc.c b/py/showbc.c index b9024b716de67..8b97c8defaeb9 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -540,7 +540,7 @@ const byte *mp_bytecode_print_str(const byte *ip) { mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI; printf("BINARY_OP " UINT_FMT " %s", op, qstr_str(mp_binary_op_method_name[op])); } else { - printf("code %p, byte code 0x%02x not implemented\n", ip, ip[-1]); + printf("code %p, byte code 0x%02x not implemented\n", ip - 1, ip[-1]); assert(0); return ip; } From 3d02ebb4e8262b67433eadc80100155387c6f186 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 1 Aug 2019 19:54:32 -0700 Subject: [PATCH 0320/1299] stm32/sdcard: Support configuring the SD/MMC bus width to 1 or 4 bits. Some SD/MMC breakout boards don't support 4-bit bus mode. This adds a new macro MICROPY_HW_SDMMC_BUS_WIDTH that allows each board to define the width of the SD/MMC bus interface used on that board, defaulting to 4 bits. --- ports/stm32/mpconfigboard_common.h | 5 +++++ ports/stm32/sdcard.c | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 121b64d038660..603215af4bf21 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -102,6 +102,11 @@ #define MICROPY_HW_ENABLE_MMCARD (0) #endif +// SD/MMC interface bus width (defaults to 4 bits) +#ifndef MICROPY_HW_SDMMC_BUS_WIDTH +#define MICROPY_HW_SDMMC_BUS_WIDTH (4) +#endif + // Whether to automatically mount (and boot from) the SD card if it's present #ifndef MICROPY_HW_SDCARD_MOUNT_AT_BOOT #define MICROPY_HW_SDCARD_MOUNT_AT_BOOT (MICROPY_HW_ENABLE_SDCARD) diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 0cb09b8189af4..f54d67ea496db 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -156,17 +156,21 @@ void sdcard_init(void) { mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_CK); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_CMD); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D0); + #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D1); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D2); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC2_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC2_D3); + #endif #else // Default SDIO/SDMMC1 config + mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_CK); + mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_CMD); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D0); + #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D1); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D2); mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_D3); - mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_CK); - mp_hal_pin_config_alt_static(MICROPY_HW_SDMMC_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_SDMMC_CMD); + #endif #endif // configure the SD card detect pin @@ -252,12 +256,14 @@ STATIC HAL_StatusTypeDef sdmmc_init_sd(void) { mp_hal_delay_ms(50); } - // configure the SD bus width for wide operation + #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 + // configure the SD bus width for 4-bit wide operation status = HAL_SD_ConfigWideBusOperation(&sdmmc_handle.sd, SDIO_BUS_WIDE_4B); if (status != HAL_OK) { HAL_SD_DeInit(&sdmmc_handle.sd); return status; } + #endif return HAL_OK; } @@ -285,7 +291,8 @@ STATIC HAL_StatusTypeDef sdmmc_init_mmc(void) { // As this is an eMMC card, overwrite LogBlockNbr with actual value sdmmc_handle.mmc.MmcCard.LogBlockNbr = 7469056 + 2048; - // Configure the SDIO bus width for wide operation + #if MICROPY_HW_SDMMC_BUS_WIDTH == 4 + // Configure the SDIO bus width for 4-bit wide operation #ifdef STM32F7 sdmmc_handle.mmc.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE; #endif @@ -294,6 +301,7 @@ STATIC HAL_StatusTypeDef sdmmc_init_mmc(void) { HAL_MMC_DeInit(&sdmmc_handle.mmc); return status; } + #endif return HAL_OK; } From b6906fa573bb1fcde5004e83b40832ae9ba8b002 Mon Sep 17 00:00:00 2001 From: Kenta IDA Date: Wed, 10 Jul 2019 00:30:38 +0900 Subject: [PATCH 0321/1299] esp32/network_ppp: Add authentication support to the PPP interface. This commit adds the connect() method to the PPP interface and requires that connect() be called after active(1). This is a breaking change for the PPP API. With the connect() method it's now possible to pass in authentication information for PAP/CHAP, eg: ppp.active(1) ppp.connect(authmode=ppp.AUTH_PAP, username="user", "password="password") If no authentication is needed simply call connect() without any parameters. This will get the original behaviour of calling active(1). --- ports/esp32/network_ppp.c | 86 +++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index aca4bbc1e9b51..1a14c09bf8ddb 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -129,29 +129,26 @@ STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { if (self->pcb == NULL) { mp_raise_msg(&mp_type_RuntimeError, "init failed"); } - pppapi_set_default(self->pcb); - ppp_set_usepeerdns(self->pcb, 1); - pppapi_connect(self->pcb, 0); - - xTaskCreatePinnedToCore(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle, MP_TASK_COREID); self->active = true; } else { if (!self->active) { return mp_const_false; } - // Wait for PPPERR_USER, with timeout - pppapi_close(self->pcb, 0); - uint32_t t0 = mp_hal_ticks_ms(); - while (!self->clean_close && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { - mp_hal_delay_ms(10); - } + if (self->client_task_handle != NULL) { // is connecting or connected? + // Wait for PPPERR_USER, with timeout + pppapi_close(self->pcb, 0); + uint32_t t0 = mp_hal_ticks_ms(); + while (!self->clean_close && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { + mp_hal_delay_ms(10); + } - // Shutdown task - xTaskNotifyGive(self->client_task_handle); - t0 = mp_hal_ticks_ms(); - while (self->client_task_handle != NULL && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { - mp_hal_delay_ms(10); + // Shutdown task + xTaskNotifyGive(self->client_task_handle); + t0 = mp_hal_ticks_ms(); + while (self->client_task_handle != NULL && mp_hal_ticks_ms() - t0 < PPP_CLOSE_TIMEOUT_MS) { + mp_hal_delay_ms(10); + } } // Release PPP @@ -166,6 +163,59 @@ STATIC mp_obj_t ppp_active(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ppp_active_obj, 1, 2, ppp_active); +STATIC mp_obj_t ppp_connect_py(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + enum { ARG_authmode, ARG_username, ARG_password }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_authmode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PPPAUTHTYPE_NONE} }, + { MP_QSTR_username, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_password, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + }; + + mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args); + + ppp_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if (!self->active) { + mp_raise_msg(&mp_type_OSError, "must be active"); + } + + if (self->client_task_handle != NULL) { + mp_raise_OSError(MP_EALREADY); + } + + switch (parsed_args[ARG_authmode].u_int) { + case PPPAUTHTYPE_NONE: + case PPPAUTHTYPE_PAP: + case PPPAUTHTYPE_CHAP: + break; + default: + mp_raise_msg(&mp_type_ValueError, "invalid auth"); + } + + if (parsed_args[ARG_authmode].u_int != PPPAUTHTYPE_NONE) { + const char* username_str = mp_obj_str_get_str(parsed_args[ARG_username].u_obj); + const char* password_str = mp_obj_str_get_str(parsed_args[ARG_password].u_obj); + pppapi_set_auth(self->pcb, parsed_args[ARG_authmode].u_int, username_str, password_str); + } + if (pppapi_set_default(self->pcb) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "set default failed"); + } + + ppp_set_usepeerdns(self->pcb, true); + + if (pppapi_connect(self->pcb, 0) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "connect failed"); + } + + if (xTaskCreatePinnedToCore(pppos_client_task, "ppp", 2048, self, 1, (TaskHandle_t*)&self->client_task_handle, MP_TASK_COREID) != pdPASS) { + mp_raise_msg(&mp_type_RuntimeError, "failed to create worker task"); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(ppp_connect_obj, 1, ppp_connect_py); + STATIC mp_obj_t ppp_delete(mp_obj_t self_in) { ppp_if_obj_t* self = MP_OBJ_TO_PTR(self_in); mp_obj_t args[] = {self, mp_const_false}; @@ -216,10 +266,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(ppp_isconnected_obj, ppp_isconnected); STATIC const mp_rom_map_elem_t ppp_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&ppp_active_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&ppp_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&ppp_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&ppp_status_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&ppp_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ppp_delete_obj) }, + { MP_ROM_QSTR(MP_QSTR_AUTH_NONE), MP_ROM_INT(PPPAUTHTYPE_NONE) }, + { MP_ROM_QSTR(MP_QSTR_AUTH_PAP), MP_ROM_INT(PPPAUTHTYPE_PAP) }, + { MP_ROM_QSTR(MP_QSTR_AUTH_CHAP), MP_ROM_INT(PPPAUTHTYPE_CHAP) }, }; STATIC MP_DEFINE_CONST_DICT(ppp_if_locals_dict, ppp_if_locals_dict_table); From ba607809f210ae9648709138623ddadbfb16fe57 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 12:03:32 +1000 Subject: [PATCH 0322/1299] stm32/modpyb: Support building with PY_PYB_LEGACY on and HW_USB_HID off. --- ports/stm32/modpyb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index 139defc53bde3..1a1f567a5f670 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -170,9 +170,11 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { #if MICROPY_PY_PYB_LEGACY // these 2 are deprecated; use USB_VCP.isconnected and USB_HID.send instead { MP_ROM_QSTR(MP_QSTR_have_cdc), MP_ROM_PTR(&pyb_have_cdc_obj) }, + #if MICROPY_HW_USB_HID { MP_ROM_QSTR(MP_QSTR_hid), MP_ROM_PTR(&pyb_hid_send_report_obj) }, #endif #endif + #endif #if MICROPY_PY_PYB_LEGACY { MP_ROM_QSTR(MP_QSTR_millis), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, From bf733c27bbfe40c2f35407a031a2900bc4eaeaba Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 12:19:28 +1000 Subject: [PATCH 0323/1299] stm32/usbd: Introduce MICROPY_HW_USB_IS_MULTI_OTG to simplify USB config This is an internal config value that is enabled for MCUs that have multiple OTG instances, to simplify #if configuration of the USB code. --- ports/stm32/mpconfigboard_common.h | 7 +++++++ ports/stm32/usbd_cdc_interface.c | 4 ++-- ports/stm32/usbd_conf.c | 12 ++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 603215af4bf21..a7a48aabc4f76 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -287,6 +287,13 @@ #define MICROPY_HW_MAX_CAN (1) #endif +// Whether the USB peripheral is device-only, or multiple OTG +#if defined(STM32L0) || defined(STM32WB) +#define MICROPY_HW_USB_IS_MULTI_OTG (0) +#else +#define MICROPY_HW_USB_IS_MULTI_OTG (1) +#endif + // Configure maximum number of CDC VCP interfaces, and whether MSC/HID are supported #ifndef MICROPY_HW_USB_CDC_NUM #define MICROPY_HW_USB_CDC_NUM (1) diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index e234230196cc7..51d29b30fe883 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -142,7 +142,7 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, ui // configure its serial port (in most cases to disable local echo) cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING; usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs - #if defined(STM32L0) || defined(STM32WB) + #if !MICROPY_HW_USB_IS_MULTI_OTG USB->CNTR |= USB_CNTR_SOFM; #else PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData; @@ -219,7 +219,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { --usbd_cdc_connect_tx_timer; } else { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; - #if defined(STM32L0) || defined(STM32WB) + #if !MICROPY_HW_USB_IS_MULTI_OTG USB->CNTR &= ~USB_CNTR_SOFM; #else hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 437d96ae7877f..7577ee21b209e 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -44,8 +44,8 @@ PCD_HandleTypeDef pcd_fs_handle; PCD_HandleTypeDef pcd_hs_handle; #endif -#if defined(STM32L0) || defined(STM32WB) -// The STM32L0xx has a single USB device-only instance +#if !MICROPY_HW_USB_IS_MULTI_OTG +// The MCU has a single USB device-only instance #define USB_OTG_FS USB #endif @@ -92,7 +92,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #endif // Enable USB FS Clocks - #if defined(STM32L0) || defined(STM32WB) + #if !MICROPY_HW_USB_IS_MULTI_OTG __HAL_RCC_USB_CLK_ENABLE(); #else __USB_OTG_FS_CLK_ENABLE(); @@ -195,7 +195,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { * @retval None */ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { - #if defined(STM32L0) || defined(STM32WB) + #if !MICROPY_HW_USB_IS_MULTI_OTG __HAL_RCC_USB_CLK_DISABLE(); #else @@ -379,7 +379,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { pcd_fs_handle.Init.lpm_enable = DISABLE; pcd_fs_handle.Init.battery_charging_enable = DISABLE; #endif - #if !defined(STM32L0) && !defined(STM32WB) + #if MICROPY_HW_USB_IS_MULTI_OTG pcd_fs_handle.Init.use_dedicated_ep1 = 0; pcd_fs_handle.Init.dma_enable = 0; #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN) @@ -396,7 +396,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { // Initialize LL Driver HAL_PCD_Init(&pcd_fs_handle); - #if defined(STM32L0) || defined(STM32WB) + #if !MICROPY_HW_USB_IS_MULTI_OTG // We have 512 16-bit words it total to use here (when using PCD_SNG_BUF) HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0 HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0 From 97e8e036c5e01666d210ae2bf8cf2eb7f65e83e8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 12:46:04 +1000 Subject: [PATCH 0324/1299] stm32/usbd: Support USB device mode on STM32L432 MCUs. --- ports/stm32/mpconfigboard_common.h | 2 +- ports/stm32/stm32_it.c | 2 +- ports/stm32/usbd_conf.c | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index a7a48aabc4f76..d353468f96ab3 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -288,7 +288,7 @@ #endif // Whether the USB peripheral is device-only, or multiple OTG -#if defined(STM32L0) || defined(STM32WB) +#if defined(STM32L0) || defined(STM32L432xx) || defined(STM32WB) #define MICROPY_HW_USB_IS_MULTI_OTG (0) #else #define MICROPY_HW_USB_IS_MULTI_OTG (1) diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 16db92d1d7aa3..a2ebb6641a45e 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -298,7 +298,7 @@ void DebugMon_Handler(void) { /* file (startup_stm32f4xx.s). */ /******************************************************************************/ -#if defined(STM32L0) +#if defined(STM32L0) || defined(STM32L432xx) #if MICROPY_HW_USB_FS void USB_IRQHandler(void) { diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 7577ee21b209e..275ec15aa61ca 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -64,6 +64,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { const uint32_t otg_alt = GPIO_AF10_OTG1_FS; #elif defined(STM32L0) const uint32_t otg_alt = GPIO_AF0_USB; + #elif defined(STM32L432xx) + const uint32_t otg_alt = GPIO_AF10_USB_FS; #elif defined(STM32WB) const uint32_t otg_alt = GPIO_AF10_USB; #else @@ -113,6 +115,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #if defined(STM32L0) NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_IRQn); + #elif defined(STM32L432xx) + NVIC_SetPriority(USB_FS_IRQn, IRQ_PRI_OTG_FS); + HAL_NVIC_EnableIRQ(USB_FS_IRQn); #elif defined(STM32WB) NVIC_SetPriority(USB_LP_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_LP_IRQn); From 8485b72d0d29b7985983a7328d2a84e87a4b47d5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 12:46:34 +1000 Subject: [PATCH 0325/1299] stm32/boards/NUCLEO_L432KC: Add config for USB VCP support. --- ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h index 7f2ebbad552be..60e053f44fa1c 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h @@ -14,6 +14,7 @@ #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_ADC (1) #define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (0) // requires a custom USB connector on PA11/PA12 #define MICROPY_HW_ENABLE_TIMER (1) #define MICROPY_HW_HAS_SWITCH (0) @@ -57,4 +58,8 @@ #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config -#define MICROPY_HW_USB_FS (0) +#define MICROPY_HW_USB_FS (MICROPY_HW_ENABLE_USB) +#define MICROPY_HW_USB_MSC (0) +#define MICROPY_HW_USB_HID (0) +#define USBD_CDC_RX_DATA_SIZE (256) +#define USBD_CDC_TX_DATA_SIZE (256) From 25d3509986aadb8f2a0d4d87d75b64223087512a Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 1 Aug 2019 21:49:17 +1000 Subject: [PATCH 0326/1299] stm32/usbd: Make USB device FIFO sizes dynamically configurable. Allows to optimise and configure the FIFO sizes depending on the USB device configuration selected at runtime, eg VCP+MSC vs 3xVCP+MSC. --- ports/stm32/mboot/main.c | 9 +++- ports/stm32/usb.c | 58 ++++++++++++++++++++++- ports/stm32/usbd_conf.c | 62 +++++++------------------ ports/stm32/usbd_conf.h | 10 ++++ ports/stm32/usbdev/core/inc/usbd_core.h | 2 +- ports/stm32/usbdev/core/src/usbd_core.c | 2 + 6 files changed, 96 insertions(+), 47 deletions(-) diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c index f6b89004d4162..fcd43edc7f3ea 100644 --- a/ports/stm32/mboot/main.c +++ b/ports/stm32/mboot/main.c @@ -1088,6 +1088,13 @@ typedef struct _pyb_usbdd_obj_t { #define MBOOT_USB_PID 0xDF11 #endif +static const uint8_t usbd_fifo_size[] = { + 32, 8, 16, 8, 16, 0, 0, // FS: RX, EP0(in), 5x IN endpoints + #if MICROPY_HW_USB_HS + 116, 8, 64, 4, 64, 0, 0, 0, 0, 0, // HS: RX, EP0(in), 8x IN endpoints + #endif +}; + __ALIGN_BEGIN static const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, @@ -1315,7 +1322,7 @@ static void pyb_usbdd_start(pyb_usbdd_obj_t *self) { while (!(PWR->CR3 & PWR_CR3_USB33RDY)) { } #endif - USBD_LL_Init(&self->hUSBDDevice, 0); + USBD_LL_Init(&self->hUSBDDevice, 0, usbd_fifo_size); USBD_LL_Start(&self->hUSBDDevice); self->started = true; } diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 3308f07449833..791a6472a5a40 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -75,6 +75,50 @@ typedef struct _usb_device_t { usb_device_t usb_device = {0}; pyb_usb_storage_medium_t pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_NONE; +#if !MICROPY_HW_USB_IS_MULTI_OTG + +// Units of FIFO size arrays below are 4x 16-bit words = 8 bytes +// There are 512x 16-bit words it total to use here (when using PCD_SNG_BUF) + +// EP0(out), EP0(in), MSC/HID(out), MSC/HID(in), unused, CDC_CMD(in), CDC_DATA(out), CDC_DATA(in) +STATIC const uint8_t usbd_fifo_size_cdc1[] = {16, 16, 16, 16, 0, 16, 16, 16}; + +#else + +// Units of FIFO size arrays below are 4x 32-bit words = 16 bytes +// FS: there are 320x 32-bit words in total to use here +// HS: there are 1024x 32-bit words in total to use here + +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA +STATIC const uint8_t usbd_fifo_size_cdc1[] = { + 32, 8, 16, 8, 16, 0, 0, // FS: RX, EP0(in), 5x IN endpoints + #if MICROPY_HW_USB_HS + 116, 8, 64, 4, 64, 0, 0, 0, 0, 0, // HS: RX, EP0(in), 8x IN endpoints + #endif +}; + +#if MICROPY_HW_USB_CDC_NUM >= 2 +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA +STATIC const uint8_t usbd_fifo_size_cdc2[] = { + 32, 8, 16, 4, 8, 4, 8, + #if MICROPY_HW_USB_HS + 116, 8, 64, 2, 32, 2, 32, 0, 0, 0, + #endif +}; +#endif + +#if MICROPY_HW_USB_CDC_NUM >= 3 +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA, CDC3_CMD, CDC3_DATA +STATIC const uint8_t usbd_fifo_size_cdc3[] = { + 0, 0, 0, 0, 0, 0, 0, // FS: can't support 3x VCP mode + #if MICROPY_HW_USB_HS + 82, 8, 64, 2, 32, 2, 32, 2, 32, 0, + #endif +}; +#endif + +#endif + #if MICROPY_HW_USB_HID // predefined hid mouse data STATIC const mp_obj_str_t pyb_usb_hid_mouse_desc_obj = { @@ -197,8 +241,20 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size USBD_MSC_RegisterStorage(&usb_dev->usbd_cdc_msc_hid_state, (USBD_StorageTypeDef*)&usbd_msc_fops); #endif + const uint8_t *fifo_size = usbd_fifo_size_cdc1; + #if MICROPY_HW_USB_CDC_NUM >= 3 + if (mode & USBD_MODE_IFACE_CDC(2)) { + fifo_size = usbd_fifo_size_cdc3; + } else + #endif + #if MICROPY_HW_USB_CDC_NUM >= 2 + if (mode & USBD_MODE_IFACE_CDC(1)) { + fifo_size = usbd_fifo_size_cdc2; + } + #endif + // start the USB device - USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0); + USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0, fifo_size); USBD_LL_Start(usbd); usb_dev->enabled = true; } diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 275ec15aa61ca..d30f28b2fc60c 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -361,7 +361,7 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { * @param pdev: Device handle * @retval USBD Status */ -USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const uint8_t *fifo_size) { #if MICROPY_HW_USB_FS if (pdev->id == USB_PHY_FS_ID) { #if defined(STM32WB) @@ -401,35 +401,19 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { // Initialize LL Driver HAL_PCD_Init(&pcd_fs_handle); + // Set FIFO buffer sizes #if !MICROPY_HW_USB_IS_MULTI_OTG - // We have 512 16-bit words it total to use here (when using PCD_SNG_BUF) - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0 - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0 - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x01, PCD_SNG_BUF, 192); // MSC / HID - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x81, PCD_SNG_BUF, 256); // MSC / HID - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x02, PCD_SNG_BUF, 320); // unused - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x82, PCD_SNG_BUF, 320); // CDC CMD - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x03, PCD_SNG_BUF, 384); // CDC DATA - HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x83, PCD_SNG_BUF, 448); // CDC DATA - #else - - // We have 320 32-bit words in total to use here - #if MICROPY_HW_USB_CDC_NUM == 2 - HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128); - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 0, 32); // EP0 - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 1, 64); // MSC / HID - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 16); // CDC CMD - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 32); // CDC DATA - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 4, 16); // CDC2 CMD - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 5, 32); // CDC2 DATA + uint32_t fifo_offset = USBD_PMA_RESERVE; // need to reserve some data at start of FIFO + for (size_t i = 0; i < USBD_PMA_NUM_FIFO; ++i) { + uint16_t ep_addr = ((i & 1) * 0x80) | (i >> 1); + HAL_PCDEx_PMAConfig(&pcd_fs_handle, ep_addr, PCD_SNG_BUF, fifo_offset); + fifo_offset += fifo_size[i] * 4; + } #else - HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128); - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 0, 32); // EP0 - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 1, 64); // MSC / HID - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 2, 32); // CDC CMD - HAL_PCD_SetTxFiFo(&pcd_fs_handle, 3, 64); // CDC DATA - #endif - + HAL_PCD_SetRxFiFo(&pcd_fs_handle, fifo_size[0] * 4); + for (size_t i = 0; i < USBD_FS_NUM_TX_FIFO; ++i) { + HAL_PCD_SetTxFiFo(&pcd_fs_handle, i, fifo_size[1 + i] * 4); + } #endif } #endif @@ -486,22 +470,12 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { // Initialize LL Driver HAL_PCD_Init(&pcd_hs_handle); - // We have 1024 32-bit words in total to use here - #if MICROPY_HW_USB_CDC_NUM == 3 - HAL_PCD_SetRxFiFo(&pcd_hs_handle, 328); - #else - HAL_PCD_SetRxFiFo(&pcd_hs_handle, 464); - #endif - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 0, 32); // EP0 - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 1, 256); // MSC / HID - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 2, 8); // CDC CMD - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 3, 128); // CDC DATA - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 4, 8); // CDC2 CMD - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 5, 128); // CDC2 DATA - #if MICROPY_HW_USB_CDC_NUM == 3 - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 6, 8); // CDC3 CMD - HAL_PCD_SetTxFiFo(&pcd_hs_handle, 7, 128); // CDC3 DATA - #endif + // Set FIFO buffer sizes + fifo_size += USBD_FS_NUM_FIFO; // skip over FS FIFO size values + HAL_PCD_SetRxFiFo(&pcd_hs_handle, fifo_size[0] * 4); + for (size_t i = 0; i < USBD_HS_NUM_TX_FIFO; ++i) { + HAL_PCD_SetTxFiFo(&pcd_hs_handle, i, fifo_size[1 + i] * 4); + } } #endif // MICROPY_HW_USB_HS diff --git a/ports/stm32/usbd_conf.h b/ports/stm32/usbd_conf.h index 639b54d9f39c0..83629bfc4f766 100644 --- a/ports/stm32/usbd_conf.h +++ b/ports/stm32/usbd_conf.h @@ -49,6 +49,16 @@ #endif #define USBD_DEBUG_LEVEL 0 +// For MCUs with a device-only USB peripheral +#define USBD_PMA_RESERVE (64) +#define USBD_PMA_NUM_FIFO (8) + +// For MCUs with multiple OTG USB peripherals +#define USBD_FS_NUM_TX_FIFO (6) +#define USBD_FS_NUM_FIFO (1 + USBD_FS_NUM_TX_FIFO) +#define USBD_HS_NUM_TX_FIFO (9) +#define USBD_HS_NUM_FIFO (1 + USBD_HS_NUM_TX_FIFO) + #endif // MICROPY_INCLUDED_STM32_USBD_CONF_H /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/ports/stm32/usbdev/core/inc/usbd_core.h b/ports/stm32/usbdev/core/inc/usbd_core.h index 5494be3a22ec2..d3925fc6b7148 100644 --- a/ports/stm32/usbdev/core/inc/usbd_core.h +++ b/ports/stm32/usbdev/core/inc/usbd_core.h @@ -111,7 +111,7 @@ USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev); /* USBD Low Level Driver */ -USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev, int high_speed); +USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev, int high_speed, const uint8_t *fifo_size); USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev); USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev); diff --git a/ports/stm32/usbdev/core/src/usbd_core.c b/ports/stm32/usbdev/core/src/usbd_core.c index f235b24ee6c3e..4c69a77eb60c6 100644 --- a/ports/stm32/usbdev/core/src/usbd_core.c +++ b/ports/stm32/usbdev/core/src/usbd_core.c @@ -85,6 +85,7 @@ * @{ */ +#if 0 /** * @brief USBD_Init * Initailizes the device stack and load the class driver @@ -122,6 +123,7 @@ USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef * return USBD_OK; } +#endif /** * @brief USBD_DeInit From 2ccf030fd1ee7ddf7c015217c7fbc9996c735fd1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 10 Jul 2019 15:38:48 +1000 Subject: [PATCH 0327/1299] esp32: Add support for mDNS queries and responder. They are both enabled by default, but can be disabled by defining MICROPY_HW_ENABLE_MDNS_QUERIES and/or MICROPY_HW_ENABLE_MDNS_RESPONDER to 0. The hostname for the responder is currently taken from tcpip_adapter_get_hostname() but should eventually be configurable. --- ports/esp32/Makefile | 6 ++++ ports/esp32/modnetwork.c | 20 +++++++++++++ ports/esp32/modsocket.c | 57 +++++++++++++++++++++++++++++++++++++- ports/esp32/mpconfigport.h | 8 ++++++ 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index c6ef04b465225..f30a7cfadd055 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -74,6 +74,7 @@ INC += -I$(BUILD) INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader +INC_ESPCOMP += -I$(ESPCOMP)/console INC_ESPCOMP += -I$(ESPCOMP)/driver/include INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include @@ -103,6 +104,8 @@ INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include +INC_ESPCOMP += -I$(ESPCOMP)/mdns/include +INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include INC_ESPCOMP += -I$(ESPCOMP)/ulp/include INC_ESPCOMP += -I$(ESPCOMP)/vfs/include @@ -346,6 +349,8 @@ ESPIDF_MBEDTLS_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/mbedtls/port/*.c) \ ) +ESPIDF_MDNS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/mdns/*.c)) + $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DALLOW_EVEN_MOD -D__ets__ -Wno-strict-aliasing ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/wpa_supplicant/port/*.c) \ @@ -390,6 +395,7 @@ $(eval $(call gen_espidf_lib_rule,spi_flash,$(ESPIDF_SPI_FLASH_O))) $(eval $(call gen_espidf_lib_rule,ulp,$(ESPIDF_ULP_O))) $(eval $(call gen_espidf_lib_rule,lwip,$(ESPIDF_LWIP_O))) $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) +$(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O))) $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 84625760587cb..3dfe3945bb9d9 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -48,6 +48,7 @@ #include "esp_event_loop.h" #include "lwip/dns.h" #include "tcpip_adapter.h" +#include "mdns.h" #include "modnetwork.h" @@ -128,6 +129,11 @@ static bool wifi_sta_connected = false; // Store the current status. 0 means None here, safe to do so as first enum value is WIFI_REASON_UNSPECIFIED=1. static uint8_t wifi_sta_disconn_reason = 0; +#if MICROPY_HW_ENABLE_MDNS_QUERIES || MICROPY_HW_ENABLE_MDNS_RESPONDER +// Whether mDNS has been initialised or not +static bool mdns_initialised = false; +#endif + // This function is called by the system-event task and so runs in a different // thread to the main MicroPython task. It must not raise any Python exceptions. static esp_err_t event_handler(void *ctx, system_event_t *event) { @@ -142,6 +148,20 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) { ESP_LOGI("network", "GOT_IP"); wifi_sta_connected = true; wifi_sta_disconn_reason = 0; // Success so clear error. (in case of new error will be replaced anyway) + #if MICROPY_HW_ENABLE_MDNS_QUERIES || MICROPY_HW_ENABLE_MDNS_RESPONDER + if (!mdns_initialised) { + mdns_init(); + #if MICROPY_HW_ENABLE_MDNS_RESPONDER + const char *hostname = NULL; + if (tcpip_adapter_get_hostname(WIFI_IF_STA, &hostname) != ESP_OK || hostname == NULL) { + hostname = "esp32"; + } + mdns_hostname_set(hostname); + mdns_instance_name_set(hostname); + #endif + mdns_initialised = true; + } + #endif break; case SYSTEM_EVENT_STA_DISCONNECTED: { // This is a workaround as ESP32 WiFi libs don't currently diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index 8b80e631dbbf2..a6f29718d8e17 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -47,6 +47,7 @@ #include "py/mperrno.h" #include "lib/netutils/netutils.h" #include "tcpip_adapter.h" +#include "mdns.h" #include "modnetwork.h" #include "lwip/sockets.h" @@ -56,6 +57,8 @@ #include "esp_log.h" #define SOCKET_POLL_US (100000) +#define MDNS_QUERY_TIMEOUT_MS (5000) +#define MDNS_LOCAL_SUFFIX ".local" typedef struct _socket_obj_t { mp_obj_base_t base; @@ -150,6 +153,58 @@ static inline void check_for_exceptions(void) { mp_handle_pending(); } +// This function mimics lwip_getaddrinfo, with added support for mDNS queries +static int _socket_getaddrinfo3(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) { + + #if MICROPY_HW_ENABLE_MDNS_QUERIES + int nodename_len = strlen(nodename); + const int local_len = sizeof(MDNS_LOCAL_SUFFIX) - 1; + if (nodename_len > local_len + && strcasecmp(nodename + nodename_len - local_len, MDNS_LOCAL_SUFFIX) == 0) { + // mDNS query + char nodename_no_local[nodename_len - local_len + 1]; + memcpy(nodename_no_local, nodename, nodename_len - local_len); + nodename_no_local[nodename_len - local_len] = '\0'; + + struct ip4_addr addr = {0}; + esp_err_t err = mdns_query_a(nodename_no_local, MDNS_QUERY_TIMEOUT_MS, &addr); + if (err != ESP_OK) { + if (err == ESP_ERR_NOT_FOUND){ + *res = NULL; + return 0; + } + *res = NULL; + return err; + } + + struct addrinfo *ai = memp_malloc(MEMP_NETDB); + if (ai == NULL) { + *res = NULL; + return EAI_MEMORY; + } + memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); + + struct sockaddr_in *sa = (struct sockaddr_in*)((uint8_t*)ai + sizeof(struct addrinfo)); + inet_addr_from_ip4addr(&sa->sin_addr, &addr); + sa->sin_family = AF_INET; + sa->sin_len = sizeof(struct sockaddr_in); + sa->sin_port = lwip_htons((u16_t)atoi(servname)); + ai->ai_family = AF_INET; + ai->ai_canonname = ((char*)sa + sizeof(struct sockaddr_storage)); + memcpy(ai->ai_canonname, nodename, nodename_len + 1); + ai->ai_addrlen = sizeof(struct sockaddr_storage); + ai->ai_addr = (struct sockaddr*)sa; + + *res = ai; + return 0; + } + #endif + + // Normal query + return lwip_getaddrinfo(nodename, servname, hints, res); +} + static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) { const struct addrinfo hints = { .ai_family = AF_INET, @@ -172,7 +227,7 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc } MP_THREAD_GIL_EXIT(); - int res = lwip_getaddrinfo(host_str, port_str, &hints, resp); + int res = _socket_getaddrinfo3(host_str, port_str, &hints, resp); MP_THREAD_GIL_ENTER(); return res; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 9ffe380fca063..b5c7f50792ff5 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -272,3 +272,11 @@ typedef long mp_off_t; #define MICROPY_HW_BOARD_NAME "ESP32 module" #define MICROPY_HW_MCU_NAME "ESP32" #define MICROPY_PY_SYS_PLATFORM "esp32" + +#ifndef MICROPY_HW_ENABLE_MDNS_QUERIES +#define MICROPY_HW_ENABLE_MDNS_QUERIES (1) +#endif + +#ifndef MICROPY_HW_ENABLE_MDNS_RESPONDER +#define MICROPY_HW_ENABLE_MDNS_RESPONDER (1) +#endif From cb3647004fbf7b069a3509a02b72420828369bd3 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 5 Aug 2019 15:06:41 +0200 Subject: [PATCH 0328/1299] py: Implement new sys.atexit feature. This patch implements a new sys.atexit function which registers a function that is later executed when the main script ends. It is configurable via MICROPY_PY_SYS_ATEXIT, disabled by default. This is not compliant with CPython, rather it can be used to implement a CPython compatible "atexit" module if desired (similar to how sys.print_exception can be used to implement functionality of the "traceback" module). --- py/modsys.c | 13 +++++++++++++ py/mpconfig.h | 5 +++++ py/mpstate.h | 5 +++++ py/runtime.c | 4 ++++ 4 files changed, 27 insertions(+) diff --git a/py/modsys.c b/py/modsys.c index 3434517328720..3a91393812265 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -146,6 +146,16 @@ STATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof); #endif +#if MICROPY_PY_SYS_ATEXIT +// atexit(callback): Callback is called when sys.exit is called. +STATIC mp_obj_t mp_sys_atexit(mp_obj_t obj) { + mp_obj_t old = MP_STATE_VM(sys_exitfunc); + MP_STATE_VM(sys_exitfunc) = obj; + return old; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_atexit_obj, mp_sys_atexit); +#endif + STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) }, @@ -201,6 +211,9 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { */ { MP_ROM_QSTR(MP_QSTR_print_exception), MP_ROM_PTR(&mp_sys_print_exception_obj) }, + #if MICROPY_PY_SYS_ATEXIT + { MP_ROM_QSTR(MP_QSTR_atexit), MP_ROM_PTR(&mp_sys_atexit_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table); diff --git a/py/mpconfig.h b/py/mpconfig.h index a111b27aec2e8..bded9da9fcd22 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1161,6 +1161,11 @@ typedef double mp_float_t; #define MICROPY_PY_SYS_EXIT (1) #endif +// Whether to provide "sys.atexit" function (MicroPython extension) +#ifndef MICROPY_PY_SYS_ATEXIT +#define MICROPY_PY_SYS_ATEXIT (0) +#endif + // Whether to provide "sys.getsizeof" function #ifndef MICROPY_PY_SYS_GETSIZEOF #define MICROPY_PY_SYS_GETSIZEOF (0) diff --git a/py/mpstate.h b/py/mpstate.h index b7eb6bdeb1505..1057cef04185d 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -149,6 +149,11 @@ typedef struct _mp_state_vm_t { mp_obj_base_t *cur_exception; #endif + #if MICROPY_PY_SYS_ATEXIT + // exposed through sys.atexit function + mp_obj_t sys_exitfunc; + #endif + // dictionary for the __main__ module mp_obj_dict_t dict_main; diff --git a/py/runtime.c b/py/runtime.c index 70d7957198ea7..04f9442b7b6a6 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -118,6 +118,10 @@ void mp_init(void) { MP_STATE_VM(vfs_mount_table) = NULL; #endif + #if MICROPY_PY_SYS_ATEXIT + MP_STATE_VM(sys_exitfunc) = mp_const_none; + #endif + #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif From 6f0c6bd77410ad25ade6a3999c62451ae76ea60a Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 5 Aug 2019 15:11:24 +0200 Subject: [PATCH 0329/1299] unix: Enable sys.atexit, triggered after the main script ends. --- ports/unix/main.c | 6 ++++++ ports/unix/mpconfigport.h | 1 + 2 files changed, 7 insertions(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index cd2dc49a52788..004d581bb22ef 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -642,6 +642,12 @@ MP_NOINLINE int main_(int argc, char **argv) { } } + #if MICROPY_PY_SYS_ATEXIT + if (mp_obj_is_callable(MP_STATE_VM(sys_exitfunc))) { + mp_call_function_0(MP_STATE_VM(sys_exitfunc)); + } + #endif + #if MICROPY_PY_MICROPYTHON_MEM_INFO if (mp_verbose_flag) { mp_micropython_mem_info(0, NULL); diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 97a9f4908415a..123cad2bc2967 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -90,6 +90,7 @@ #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_SYS_EXIT (1) +#define MICROPY_PY_SYS_ATEXIT (1) #if defined(__APPLE__) && defined(__MACH__) #define MICROPY_PY_SYS_PLATFORM "darwin" #else From 28cb15d1313c77a04d1b119089dd1b4c7ac5ebb1 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 5 Aug 2019 15:12:27 +0200 Subject: [PATCH 0330/1299] tests/misc/sys_atexit: Add test for new sys.atexit feature. --- tests/misc/sys_atexit.py | 18 ++++++++++++++++++ tests/misc/sys_atexit.py.exp | 2 ++ 2 files changed, 20 insertions(+) create mode 100644 tests/misc/sys_atexit.py create mode 100644 tests/misc/sys_atexit.py.exp diff --git a/tests/misc/sys_atexit.py b/tests/misc/sys_atexit.py new file mode 100644 index 0000000000000..f5317953c270d --- /dev/null +++ b/tests/misc/sys_atexit.py @@ -0,0 +1,18 @@ +# test sys.atexit() function + +import sys +try: + sys.atexit +except AttributeError: + print('SKIP') + raise SystemExit + +some_var = None + +def do_at_exit(): + print("done at exit:", some_var) + +sys.atexit(do_at_exit) + +some_var = "ok" +print("done before exit") diff --git a/tests/misc/sys_atexit.py.exp b/tests/misc/sys_atexit.py.exp new file mode 100644 index 0000000000000..3cbdae9a5a0aa --- /dev/null +++ b/tests/misc/sys_atexit.py.exp @@ -0,0 +1,2 @@ +done before exit +done at exit: ok From ed9c0185d80514670244b0c2147958dea00159a9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 17:42:38 +1000 Subject: [PATCH 0331/1299] docs/library/sys: Add documentation for sys.atexit function. --- docs/library/sys.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/library/sys.rst b/docs/library/sys.rst index f2d96cb8cc85d..aee2e54ee6b01 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -15,6 +15,19 @@ Functions function raise as `SystemExit` exception. If an argument is given, its value given as an argument to `SystemExit`. +.. function:: atexit(func) + + Register *func* to be called upon termination. *func* must be a callable + that takes no arguments, or ``None`` to disable the call. The ``atexit`` + function will return the previous value set by this function, which is + initially ``None``. + + .. admonition:: Difference to CPython + :class: attention + + This function is a MicroPython extension intended to provide similar + functionality to the :mod:`atexit` module in CPython. + .. function:: print_exception(exc, file=sys.stdout) Print exception with a traceback to a file-like object *file* (or From 57476a3c378940f72415c0093f1e24416132a817 Mon Sep 17 00:00:00 2001 From: Vicki Lowe Date: Tue, 6 Aug 2019 14:10:14 +1000 Subject: [PATCH 0332/1299] docs/pyboard: Update name of mounted volume to match code. --- docs/pyboard/tutorial/script.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pyboard/tutorial/script.rst b/docs/pyboard/tutorial/script.rst index 75dd324e3ca40..29a0370d8a675 100644 --- a/docs/pyboard/tutorial/script.rst +++ b/docs/pyboard/tutorial/script.rst @@ -31,7 +31,7 @@ have as to what happens next: We will get the serial device working in the next tutorial. - **Mac**: Your pyboard will appear on the desktop as a removable disc. - It will probably be called "NONAME". Click on it to open the pyboard folder. + It will probably be called ``PYBFLASH``. Click on it to open the pyboard folder. - **Linux**: Your pyboard will appear as a removable medium. On Ubuntu it will mount automatically and pop-up a window with the pyboard folder. From 6592a30f4b6ed056411361d0c703fe814886e65b Mon Sep 17 00:00:00 2001 From: Vicki Lowe Date: Tue, 6 Aug 2019 15:46:29 +1000 Subject: [PATCH 0333/1299] docs/pyboard: Clarify initial files on pyboard and fix up formatting. --- docs/pyboard/tutorial/script.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/pyboard/tutorial/script.rst b/docs/pyboard/tutorial/script.rst index 29a0370d8a675..2d44bbc885055 100644 --- a/docs/pyboard/tutorial/script.rst +++ b/docs/pyboard/tutorial/script.rst @@ -46,17 +46,17 @@ a window (or command line) should be showing the files on the pyboard drive. The drive you are looking at is known as ``/flash`` by the pyboard, and should contain the following 4 files: -* `boot.py `_ -- this script is executed when the pyboard boots up. It sets - up various configuration options for the pyboard. +* `boot.py `_ -- the various configuration options for the pyboard. + It is executed when the pyboard boots up. -* `main.py `_ -- this is the main script that will contain your Python program. +* `main.py `_ -- the Python program to be run. It is executed after ``boot.py``. -* `README.txt `_ -- this contains some very basic information about getting - started with the pyboard. +* `README.txt `_ -- basic information about getting started with the pyboard. + This provides pointers for new users and can be safely deleted. -* `pybcdc.inf `_ -- this is a Windows driver file to configure the serial USB - device. More about this in the next tutorial. +* `pybcdc.inf `_ -- the Windows driver file to configure the serial USB device. + More about this in the next tutorial. Editing ``main.py`` ------------------- From d5a77416064f8155b0a0817211541c296b49d2c7 Mon Sep 17 00:00:00 2001 From: Tom McDermott Date: Tue, 6 Aug 2019 16:18:07 +1000 Subject: [PATCH 0334/1299] docs/library: Document that sys.version_info returns a 3-tuple only. See issue #4970. --- docs/library/sys.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/library/sys.rst b/docs/library/sys.rst index aee2e54ee6b01..d3cc308d89fb8 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -134,3 +134,9 @@ Constants .. data:: version_info Python language version that this implementation conforms to, as a tuple of ints. + + .. admonition:: Difference to CPython + :class: attention + + Only the first three version numbers (major, minor, micro) are supported and + they can be referenced only by index, not by name. From afd10a45318443d67f37b2cc8fa158fe50e59f36 Mon Sep 17 00:00:00 2001 From: Vicki Lowe Date: Tue, 6 Aug 2019 17:34:34 +1000 Subject: [PATCH 0335/1299] docs/pyboard: Emphasize the instructions for making a USB mouse. It wasn't clear why that element was `10` instead of `0`. Also bumped the `10` to `100` to make the mouse movement more obvious. --- docs/pyboard/tutorial/usb_mouse.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/pyboard/tutorial/usb_mouse.rst b/docs/pyboard/tutorial/usb_mouse.rst index 6f8831edb465e..8166946ecd9e1 100644 --- a/docs/pyboard/tutorial/usb_mouse.rst +++ b/docs/pyboard/tutorial/usb_mouse.rst @@ -39,14 +39,15 @@ Sending mouse events by hand To get the py-mouse to do anything we need to send mouse events to the PC. We will first do this manually using the REPL prompt. Connect to your -pyboard using your serial program and type the following:: +pyboard using your serial program and type the following (no need to type +the ``#`` and text following it):: >>> hid = pyb.USB_HID() - >>> hid.send((0, 10, 0, 0)) + >>> hid.send((0, 100, 0, 0)) # (button status, x-direction, y-direction, scroll) -Your mouse should move 10 pixels to the right! In the command above you -are sending 4 pieces of information: button status, x, y and scroll. The -number 10 is telling the PC that the mouse moved 10 pixels in the x direction. +Your mouse should move 100 pixels to the right! In the command above you +are sending 4 pieces of information: **button status**, **x-direction**, **y-direction**, and **scroll**. The +number 100 is telling the PC that the mouse moved 100 pixels in the x direction. Let's make the mouse oscillate left and right:: From 64abc1f47a5274729b1e51b71f0691d60114242e Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 18:56:01 +1000 Subject: [PATCH 0336/1299] tests/unix: Update extra_coverage expected output with new atexit func. --- tests/unix/extra_coverage.py.exp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index a9889c0e9530b..07fde6c09cca5 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -28,11 +28,11 @@ RuntimeError: # repl ame__ -__class__ __name__ argv byteorder -exc_info exit getsizeof implementation -maxsize modules path platform -print_exception stderr stdin -stdout version version_info +__class__ __name__ argv atexit +byteorder exc_info exit getsizeof +implementation maxsize modules path +platform print_exception stderr +stdin stdout version version_info ementation # attrtuple (start=1, stop=2, step=3) From baeebc557c3132fa17f3c902e260d5049f7c7957 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 22:03:09 +1000 Subject: [PATCH 0337/1299] esp32/modules: On initial setup mount internal flash at root. Like it's done on normal boot up. Fixes issue #5004. --- ports/esp32/modules/inisetup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/esp32/modules/inisetup.py b/ports/esp32/modules/inisetup.py index 0e9c72fe86133..00d9a4eab82e8 100644 --- a/ports/esp32/modules/inisetup.py +++ b/ports/esp32/modules/inisetup.py @@ -29,8 +29,7 @@ def setup(): print("Performing initial setup") uos.VfsFat.mkfs(bdev) vfs = uos.VfsFat(bdev) - uos.mount(vfs, '/flash') - uos.chdir('/flash') + uos.mount(vfs, '/') with open("boot.py", "w") as f: f.write("""\ # This file is executed on every boot (including wake-boot from deepsleep) From acfbb9febd024475bdcb4ebbe2ec8c0e9a652275 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Aug 2019 23:02:04 +1000 Subject: [PATCH 0338/1299] py/objarray: Fix amount of free space in array when doing slice assign. Prior to this patch the amount of free space in an array (including bytearray) was not being maintained correctly for the case of slice assignment which changed the size of the array. Under certain cases (as encoded in the new test) it was possible that the array could grow beyond its allocated memory block and corrupt the heap. Fixes issue #4127. --- py/objarray.c | 3 ++- tests/basics/bytearray_slice_assign.py | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/py/objarray.c b/py/objarray.c index 4e58d8e5daa6d..c19617d4e1dd6 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -445,7 +445,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value if (len_adj > o->free) { // TODO: alloc policy; at the moment we go conservative o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz); - o->free = 0; + o->free = len_adj; dest_items = o->items; } mp_seq_replace_slice_grow_inplace(dest_items, o->len, @@ -458,6 +458,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); // TODO: alloc policy after shrinking } + o->free -= len_adj; o->len += len_adj; return mp_const_none; #else diff --git a/tests/basics/bytearray_slice_assign.py b/tests/basics/bytearray_slice_assign.py index 7f7d1d119a7d8..fa7878e10ddbb 100644 --- a/tests/basics/bytearray_slice_assign.py +++ b/tests/basics/bytearray_slice_assign.py @@ -59,3 +59,10 @@ b = bytearray(2) b[1:1] = b"12345" print(b) + +# Growth of bytearray via slice extension +b = bytearray(b'12345678') +b.append(57) # expand and add a bit of unused space at end of the bytearray +for i in range(400): + b[-1:] = b'ab' # grow slowly into the unused space +print(len(b), b) From 497683b315c0fb842a6ce528f9c4ec88f4b8ff2a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 16 Aug 2019 00:08:08 +1000 Subject: [PATCH 0339/1299] gitignore: Put build-*/ pattern in top-level gitignore file. --- .gitignore | 3 ++- ports/nrf/.gitignore | 5 ----- ports/stm32/.gitignore | 1 - ports/unix/.gitignore | 6 ------ 4 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 ports/stm32/.gitignore diff --git a/.gitignore b/.gitignore index 5e841a89c059d..50bd30e877e87 100644 --- a/.gitignore +++ b/.gitignore @@ -20,9 +20,10 @@ ###################### *.swp -# Build directory +# Build directories ###################### build/ +build-*/ # Test failure outputs ###################### diff --git a/ports/nrf/.gitignore b/ports/nrf/.gitignore index ace93515a20cf..4b46e05865781 100644 --- a/ports/nrf/.gitignore +++ b/ports/nrf/.gitignore @@ -1,8 +1,3 @@ # Nordic files ##################### drivers/bluetooth/s1*/ - -# Build files -##################### -build-*/ - diff --git a/ports/stm32/.gitignore b/ports/stm32/.gitignore deleted file mode 100644 index 414487d53eb83..0000000000000 --- a/ports/stm32/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build-*/ diff --git a/ports/unix/.gitignore b/ports/unix/.gitignore index 706b7732dc51e..7179e7bde4751 100644 --- a/ports/unix/.gitignore +++ b/ports/unix/.gitignore @@ -1,9 +1,3 @@ -build -build-fast -build-minimal -build-coverage -build-nanbox -build-freedos micropython micropython_fast micropython_minimal From 8db517f26d236023eeb04bf9af8b1e9f1c2ccec3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 9 Aug 2019 18:07:50 +1000 Subject: [PATCH 0340/1299] esp32: Add per-board configs, following other ports. Replaces the `SDKCONFIG` makefile variable with `BOARD`. Defaults to BOARD=GENERIC. spiram can be enabled with `BOARD=GENERIC_SPIRAM` Add example definition for TINYPICO, currently identical to GENERIC_SPIRAM but with custom board/SoC names for the uPy banner. --- ports/esp32/Makefile | 45 ++++++++++++++++--- ports/esp32/README.md | 20 +++++---- ports/esp32/boards/GENERIC/mpconfigboard.h | 2 + ports/esp32/boards/GENERIC/mpconfigboard.mk | 1 + .../boards/GENERIC_SPIRAM/mpconfigboard.h | 2 + .../boards/GENERIC_SPIRAM/mpconfigboard.mk | 2 + ports/esp32/boards/TINYPICO/mpconfigboard.h | 2 + ports/esp32/boards/TINYPICO/mpconfigboard.mk | 2 + .../boards/{sdkconfig => sdkconfig.base} | 0 ports/esp32/boards/sdkconfig.spiram | 28 ------------ ports/esp32/mpconfigport.h | 6 +-- 11 files changed, 63 insertions(+), 47 deletions(-) create mode 100644 ports/esp32/boards/GENERIC/mpconfigboard.h create mode 100644 ports/esp32/boards/GENERIC/mpconfigboard.mk create mode 100644 ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h create mode 100644 ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk create mode 100644 ports/esp32/boards/TINYPICO/mpconfigboard.h create mode 100644 ports/esp32/boards/TINYPICO/mpconfigboard.mk rename ports/esp32/boards/{sdkconfig => sdkconfig.base} (100%) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index f30a7cfadd055..3802c2fc9c8d4 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -1,7 +1,30 @@ +# Select the board to build for: if not given on the command line, +# then default to GENERIC. +BOARD ?= GENERIC + +# If the build directory is not given, make it reflect the board name. +BUILD ?= build-$(BOARD) + +BOARD_DIR ?= boards/$(BOARD) +ifeq ($(wildcard $(BOARD_DIR)/.),) +$(error Invalid BOARD specified: $(BOARD_DIR)) +endif + include ../../py/mkenv.mk +# Optional (not currently used for ESP32) +-include mpconfigport.mk + +ifneq ($(SDKCONFIG),) +$(error Use the BOARD variable instead of SDKCONFIG) +endif + +# Expected to set SDKCONFIG +include $(BOARD_DIR)/mpconfigboard.mk + # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h +QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 @@ -22,8 +45,7 @@ FLASH_SIZE ?= 4MB CROSS_COMPILE ?= xtensa-esp32-elf- OBJDUMP = $(CROSS_COMPILE)objdump -# SDKCONFIG should be overridden to get a different configuration -SDKCONFIG ?= boards/sdkconfig +SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined SDKCONFIG_H = $(BUILD)/sdkconfig.h # the git hash of the currently supported ESP IDF version @@ -130,6 +152,7 @@ CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_co CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) CFLAGS += -DIDF_VER=\"$(IDF_VER)\" CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += -I$(BOARD_DIR) # this is what ESPIDF uses for c++ compilation CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP) @@ -201,6 +224,7 @@ SRC_C = \ mpthreadport.c \ machine_rtc.c \ machine_sdcard.c \ + $(wildcard $(BOARD_DIR)/*.c) \ $(SRC_MOD) EXTMOD_SRC_C = $(addprefix extmod/,\ @@ -242,7 +266,11 @@ SRC_QSTR_AUTO_DEPS += ################################################################################ # Generate sdkconfig.h from sdkconfig -$(SDKCONFIG_H): $(SDKCONFIG) +$(SDKCONFIG_COMBINED): $(SDKCONFIG) + $(Q)$(MKDIR) -p $(dir $@) + $(Q)$(CAT) $^ > $@ + +$(SDKCONFIG_H): $(SDKCONFIG_COMBINED) $(ECHO) "GEN $@" $(Q)$(MKDIR) -p $(dir $@) $(Q)$(PYTHON) $(ESPIDF)/tools/kconfig_new/confgen.py \ @@ -255,7 +283,7 @@ $(SDKCONFIG_H): $(SDKCONFIG) --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" $(Q)touch $@ -$(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) +$(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard.h ################################################################################ # List of object files from the ESP32 IDF components @@ -429,12 +457,12 @@ $(eval $(foreach lib,$(LIB_ESPIDF),$(eval $(call gen_sections_info_rule,$(BUILD_ $(LDGEN_SECTION_INFOS): $(LDGEN_SECTIONS_INFO) $(ESPIDF)/make/ldgen.mk $(Q)printf "$(foreach info,$(LDGEN_SECTIONS_INFO),$(info)\n)" > $@ -$(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG) $(LDGEN_SECTION_INFOS) +$(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(LDGEN_SECTION_INFOS) $(ECHO) "GEN $@" $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ --input $< \ --output $@ \ - --config $(SDKCONFIG) \ + --config $(SDKCONFIG_COMBINED) \ --kconfig $(ESPIDF)/Kconfig \ --fragments $(LDGEN_FRAGMENTS) \ --sections $(LDGEN_SECTION_INFOS) \ @@ -472,6 +500,7 @@ OBJ = $(OBJ_MP) APP_LD_ARGS = APP_LD_ARGS += $(LDFLAGS_MOD) +APP_LD_ARGS += $(addprefix -T,$(LD_FILES)) APP_LD_ARGS += --start-group APP_LD_ARGS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ @@ -653,7 +682,9 @@ $(BUILD)/bootloader.elf: $(BOOTLOADER_OBJ) $(addprefix $(BOOTLOADER_LIB_DIR)/lib # Declarations to build the partitions PYTHON2 ?= python2 -PART_SRC = partitions.csv + +# Can be overriden by mkconfigboard.mk. +PART_SRC ?= partitions.csv $(BUILD)/partitions.bin: $(PART_SRC) $(ECHO) "Create $@" diff --git a/ports/esp32/README.md b/ports/esp32/README.md index 12144d822d9ad..31347b6a2a6a1 100644 --- a/ports/esp32/README.md +++ b/ports/esp32/README.md @@ -74,11 +74,11 @@ variables for the build. In that case, create a new file in the esp32 directory called `makefile` and add the following lines to that file: ``` ESPIDF = +BOARD = GENERIC #PORT = /dev/ttyUSB0 #FLASH_MODE = qio #FLASH_SIZE = 4MB #CROSS_COMPILE = xtensa-esp32-elf- -#SDKCONFIG = boards/sdkconfig.spiram include Makefile ``` @@ -92,16 +92,18 @@ are `PORT` for the serial port of your esp32 module, and `FLASH_MODE` (which may need to be `dio` for some modules) and `FLASH_SIZE`. See the Makefile for further information. -The default ESP IDF configuration settings are provided in the file -`boards/sdkconfig`, and this file is specified in the build by the make -variable `SDKCONFIG`. To use a custom configuration either set `SDKCONFIG` -in your custom `makefile` (or `GNUmakefile`) or set this variable on the -command line: +The default ESP IDF configuration settings are provided by the `GENERIC` +board definition in the directory `boards/GENERIC`. For a custom configuration +you can define your own board directory. + +The `BOARD` variable can be set on the make command line: ```bash -$ make SDKCONFIG=sdkconfig.myboard +$ make BOARD=TINYPICO ``` -The file `boards/sdkconfig.spiram` is provided for ESP32 modules that have -external SPIRAM. +or added to your custom `makefile` (or `GNUmakefile`) described above. There +is also a `GENERIC_SPIRAM` board for for ESP32 modules that have external +SPIRAM, but prefer to use a specific board target (or define your own as +necessary). Building the firmware --------------------- diff --git a/ports/esp32/boards/GENERIC/mpconfigboard.h b/ports/esp32/boards/GENERIC/mpconfigboard.h new file mode 100644 index 0000000000000..644807f78e601 --- /dev/null +++ b/ports/esp32/boards/GENERIC/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "ESP32 module" +#define MICROPY_HW_MCU_NAME "ESP32" diff --git a/ports/esp32/boards/GENERIC/mpconfigboard.mk b/ports/esp32/boards/GENERIC/mpconfigboard.mk new file mode 100644 index 0000000000000..fc49d2a8c256c --- /dev/null +++ b/ports/esp32/boards/GENERIC/mpconfigboard.mk @@ -0,0 +1 @@ +SDKCONFIG += boards/sdkconfig.base diff --git a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h new file mode 100644 index 0000000000000..a5982e47e5c32 --- /dev/null +++ b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "ESP32 module (spiram)" +#define MICROPY_HW_MCU_NAME "ESP32" diff --git a/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk new file mode 100644 index 0000000000000..59aa75f8571b9 --- /dev/null +++ b/ports/esp32/boards/GENERIC_SPIRAM/mpconfigboard.mk @@ -0,0 +1,2 @@ +SDKCONFIG += boards/sdkconfig.base +SDKCONFIG += boards/sdkconfig.spiram diff --git a/ports/esp32/boards/TINYPICO/mpconfigboard.h b/ports/esp32/boards/TINYPICO/mpconfigboard.h new file mode 100644 index 0000000000000..e63f43ed25a2f --- /dev/null +++ b/ports/esp32/boards/TINYPICO/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "TinyPICO" +#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4" diff --git a/ports/esp32/boards/TINYPICO/mpconfigboard.mk b/ports/esp32/boards/TINYPICO/mpconfigboard.mk new file mode 100644 index 0000000000000..59aa75f8571b9 --- /dev/null +++ b/ports/esp32/boards/TINYPICO/mpconfigboard.mk @@ -0,0 +1,2 @@ +SDKCONFIG += boards/sdkconfig.base +SDKCONFIG += boards/sdkconfig.spiram diff --git a/ports/esp32/boards/sdkconfig b/ports/esp32/boards/sdkconfig.base similarity index 100% rename from ports/esp32/boards/sdkconfig rename to ports/esp32/boards/sdkconfig.base diff --git a/ports/esp32/boards/sdkconfig.spiram b/ports/esp32/boards/sdkconfig.spiram index 1467f3171b23e..53950e587c074 100644 --- a/ports/esp32/boards/sdkconfig.spiram +++ b/ports/esp32/boards/sdkconfig.spiram @@ -1,33 +1,5 @@ # MicroPython on ESP32, ESP IDF configuration with SPIRAM support -# The following options override the defaults -CONFIG_IDF_TARGET="esp32" - -# Application manager -CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y -CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y - -# Bootloader config -CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y - -# ESP32-specific -CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_SPIRAM_SUPPORT=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_USE_MEMMAP=y -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=n -CONFIG_ESP32_XTAL_FREQ_AUTO=y - -# Power Management -CONFIG_PM_ENABLE=y - -# FreeRTOS -CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 -CONFIG_SUPPORT_STATIC_ALLOCATION=y -CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y - -# UDP -CONFIG_PPP_SUPPORT=y -CONFIG_PPP_PAP_SUPPORT=y -CONFIG_PPP_CHAP_SUPPORT=y diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index b5c7f50792ff5..364b2de5c2e88 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -1,6 +1,9 @@ // Options to control how MicroPython is built for this port, // overriding defaults in py/mpconfig.h. +// Board-specific definitions +#include "mpconfigboard.h" + #include #include #include "rom/ets_sys.h" @@ -268,9 +271,6 @@ typedef long mp_off_t; #include // board specifics - -#define MICROPY_HW_BOARD_NAME "ESP32 module" -#define MICROPY_HW_MCU_NAME "ESP32" #define MICROPY_PY_SYS_PLATFORM "esp32" #ifndef MICROPY_HW_ENABLE_MDNS_QUERIES From a5d85d306c430e0dbf3871971f68ed920dda4ef7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 10 Aug 2019 15:17:09 +1000 Subject: [PATCH 0341/1299] samd: Make common linker scripts, rename board.mk to mpconfigboard.mk. The rename matches other ports, e.g. stm32, and gives consistency with mpconfigboard.h. --- ports/samd/Makefile | 2 +- .../{board.mk => mpconfigboard.mk} | 2 +- .../boards/ADAFRUIT_TRINKET_M0/{board.mk => mpconfigboard.mk} | 2 +- .../samd/boards/{ADAFRUIT_TRINKET_M0/link.ld => samd21x18a.ld} | 0 .../{ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld => samd51g19a.ld} | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/{board.mk => mpconfigboard.mk} (56%) rename ports/samd/boards/ADAFRUIT_TRINKET_M0/{board.mk => mpconfigboard.mk} (56%) rename ports/samd/boards/{ADAFRUIT_TRINKET_M0/link.ld => samd21x18a.ld} (100%) rename ports/samd/boards/{ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld => samd51g19a.ld} (100%) diff --git a/ports/samd/Makefile b/ports/samd/Makefile index f4a09ad7c10ec..77a53bd4863df 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -10,7 +10,7 @@ $(error Invalid BOARD specified: $(BOARD_DIR)) endif include ../../py/mkenv.mk -include $(BOARD_DIR)/board.mk +include $(BOARD_DIR)/mpconfigboard.mk # Qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk similarity index 56% rename from ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk rename to ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk index 8cbd1885e464f..2e5d7e68df7d6 100644 --- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/board.mk +++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk @@ -1,4 +1,4 @@ MCU_SERIES = SAMD51 CMSIS_MCU = SAMD51G19A -LD_FILES = $(BOARD_DIR)/link.ld sections.ld +LD_FILES = boards/samd51g19a.ld sections.ld TEXT0 = 0x4000 diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.mk b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.mk similarity index 56% rename from ports/samd/boards/ADAFRUIT_TRINKET_M0/board.mk rename to ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.mk index 3955a4f7195fb..5b4d0b63e7e5a 100644 --- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/board.mk +++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.mk @@ -1,4 +1,4 @@ MCU_SERIES = SAMD21 CMSIS_MCU = SAMD21E18A -LD_FILES = $(BOARD_DIR)/link.ld sections.ld +LD_FILES = boards/samd21x18a.ld sections.ld TEXT0 = 0x2000 diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/link.ld b/ports/samd/boards/samd21x18a.ld similarity index 100% rename from ports/samd/boards/ADAFRUIT_TRINKET_M0/link.ld rename to ports/samd/boards/samd21x18a.ld diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld b/ports/samd/boards/samd51g19a.ld similarity index 100% rename from ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/link.ld rename to ports/samd/boards/samd51g19a.ld From 90188cc92beff545854e2ff55698494a175a34fc Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 10 Aug 2019 14:58:27 +1000 Subject: [PATCH 0342/1299] samd/boards: Add Adafruit Feather M0 Express board configuration. --- ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h | 2 ++ .../samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h create mode 100644 ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h new file mode 100644 index 0000000000000..cec9e9ccdda46 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "Feather M0 Express" +#define MICROPY_HW_MCU_NAME "SAMD21G18A" diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk new file mode 100644 index 0000000000000..8696c966bc321 --- /dev/null +++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.mk @@ -0,0 +1,4 @@ +MCU_SERIES = SAMD21 +CMSIS_MCU = SAMD21G18A +LD_FILES = boards/samd21x18a.ld sections.ld +TEXT0 = 0x2000 From eb7eed5d920748f8222efbd16bfb24c3d1798e83 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 10 Aug 2019 15:04:00 +1000 Subject: [PATCH 0343/1299] samd/boards: Add Mini SAM M4 board configuration. --- ports/samd/boards/MINISAM_M4/mpconfigboard.h | 7 +++++++ ports/samd/boards/MINISAM_M4/mpconfigboard.mk | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 ports/samd/boards/MINISAM_M4/mpconfigboard.h create mode 100644 ports/samd/boards/MINISAM_M4/mpconfigboard.mk diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.h b/ports/samd/boards/MINISAM_M4/mpconfigboard.h new file mode 100644 index 0000000000000..0847a45bf1a4b --- /dev/null +++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.h @@ -0,0 +1,7 @@ +#define MICROPY_HW_BOARD_NAME "Mini SAM M4" +#define MICROPY_HW_MCU_NAME "SAMD51G19A" + +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) +#define MICROPY_PY_BUILTINS_COMPLEX (0) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_CMATH (0) diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.mk b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk new file mode 100644 index 0000000000000..54ed3273d547e --- /dev/null +++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk @@ -0,0 +1,5 @@ +# https://www.minifigboards.com/mini-sam-m4/mini-sam-m4-hardware/ +MCU_SERIES = SAMD51 +CMSIS_MCU = SAMD51G19A +LD_FILES = boards/samd51g19a.ld sections.ld +TEXT0 = 0x4000 From 3eff81288cb494c7d1a9fcf0a82d4e21bbd92dd8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 16 Aug 2019 13:34:04 +1000 Subject: [PATCH 0344/1299] stm32/i2c: Fix generation of restart condition for hw I2C on F0/F7. Before this patch I2C transactions using a hardware I2C peripheral on F0/F7 MCUs would not correctly generate the I2C restart condition, and instead would generate a stop followed by a start. This is because the CR2 AUTOEND bit was being set before CR2 START when the peripheral already had the I2C bus from a previous transaction that did not generate a stop. As a consequence all combined transactions, eg read-then-write for an I2C memory transfer, generated a stop condition after the first transaction and didn't generate a stop at the very end (but still released the bus). Some I2C devices require a repeated start to function correctly. This patch fixes this by making sure the CR2 AUTOEND bit is set after the start condition and slave address have been fully transferred out. --- ports/stm32/i2c.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/stm32/i2c.c b/ports/stm32/i2c.c index 06e26d9124595..5981df11c5bd8 100644 --- a/ports/stm32/i2c.c +++ b/ports/stm32/i2c.c @@ -340,8 +340,7 @@ STATIC int i2c_wait_isr_set(i2c_t *i2c, uint32_t mask) { int i2c_start_addr(i2c_t *i2c, int rd_wrn, uint16_t addr, size_t len, bool stop) { // Enable the peripheral and send the START condition with slave address i2c->CR1 |= I2C_CR1_PE; - i2c->CR2 = stop << I2C_CR2_AUTOEND_Pos - | (len > 1) << I2C_CR2_RELOAD_Pos + i2c->CR2 = (len > 1) << I2C_CR2_RELOAD_Pos | (len > 0) << I2C_CR2_NBYTES_Pos | rd_wrn << I2C_CR2_RD_WRN_Pos | (addr & 0x7f) << 1; @@ -361,6 +360,11 @@ int i2c_start_addr(i2c_t *i2c, int rd_wrn, uint16_t addr, size_t len, bool stop) return -MP_ENODEV; } + // Configure automatic STOP if needed + if (stop) { + i2c->CR2 |= I2C_CR2_AUTOEND; + } + // Repurpose OAR1 to indicate that we loaded CR2 i2c->OAR1 = 1; From af5c998f37ddc62abfd36e0b8be511c392fc25d8 Mon Sep 17 00:00:00 2001 From: stijn Date: Tue, 2 Jul 2019 10:28:44 +0200 Subject: [PATCH 0345/1299] py/modmath: Implement math.isclose() for non-complex numbers. As per PEP 485, this function appeared in for Python 3.5. Configured via MICROPY_PY_MATH_ISCLOSE which is disabled by default, but enabled for the ports which already have MICROPY_PY_MATH_SPECIAL_FUNCTIONS enabled. --- ports/esp32/mpconfigport.h | 1 + ports/javascript/mpconfigport.h | 1 + ports/stm32/mpconfigport.h | 1 + ports/unix/mpconfigport.h | 1 + ports/windows/mpconfigport.h | 1 + py/modmath.c | 39 +++++++++++++++++++++++++++ py/mpconfig.h | 5 ++++ tests/float/math_isclose.py | 47 +++++++++++++++++++++++++++++++++ tests/float/math_isclose.py.exp | 27 +++++++++++++++++++ 9 files changed, 123 insertions(+) create mode 100644 tests/float/math_isclose.py create mode 100644 tests/float/math_isclose.py.exp diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 364b2de5c2e88..cba319245c94c 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -98,6 +98,7 @@ #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) +#define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_GC (1) #define MICROPY_PY_IO (1) diff --git a/ports/javascript/mpconfigport.h b/ports/javascript/mpconfigport.h index 228113c48e4ce..02d83f402d291 100644 --- a/ports/javascript/mpconfigport.h +++ b/ports/javascript/mpconfigport.h @@ -73,6 +73,7 @@ #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) +#define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO (1) #define MICROPY_PY_STRUCT (1) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index dbb6fa2d50670..5eb44bd46b6c3 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -114,6 +114,7 @@ #define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) +#define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_MATH_FACTORIAL (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO (1) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 123cad2bc2967..23c562e5aa3f2 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -104,6 +104,7 @@ #ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) #endif +#define MICROPY_PY_MATH_ISCLOSE (MICROPY_PY_MATH_SPECIAL_FUNCTIONS) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_IOBASE (1) #define MICROPY_PY_IO_FILEIO (1) diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index ffe7ae1443afb..1a9842609ada6 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -86,6 +86,7 @@ #define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) +#define MICROPY_PY_MATH_ISCLOSE (1) #define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_GC_COLLECT_RETVAL (1) diff --git a/py/modmath.c b/py/modmath.c index d106f240c8760..35bb44bea37c7 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -171,6 +171,42 @@ MATH_FUN_1(lgamma, lgamma) #endif //TODO: fsum +#if MICROPY_PY_MATH_ISCLOSE +STATIC mp_obj_t mp_math_isclose(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_a, ARG_b, ARG_rel_tol, ARG_abs_tol }; + static const mp_arg_t allowed_args[] = { + {MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_rel_tol, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_abs_tol, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(0)}}, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + const mp_float_t a = mp_obj_get_float(args[ARG_a].u_obj); + const mp_float_t b = mp_obj_get_float(args[ARG_b].u_obj); + const mp_float_t rel_tol = args[ARG_rel_tol].u_obj == MP_OBJ_NULL + ? (mp_float_t)1e-9 : mp_obj_get_float(args[ARG_rel_tol].u_obj); + const mp_float_t abs_tol = mp_obj_get_float(args[ARG_abs_tol].u_obj); + if (rel_tol < (mp_float_t)0.0 || abs_tol < (mp_float_t)0.0) { + math_error(); + } + if (a == b) { + return mp_const_true; + } + const mp_float_t difference = MICROPY_FLOAT_C_FUN(fabs)(a - b); + if (isinf(difference)) { // Either a or b is inf + return mp_const_false; + } + if ((difference <= abs_tol) || + (difference <= MICROPY_FLOAT_C_FUN(fabs)(rel_tol * a)) || + (difference <= MICROPY_FLOAT_C_FUN(fabs)(rel_tol * b))) { + return mp_const_true; + } + return mp_const_false; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_math_isclose_obj, 2, mp_math_isclose); +#endif + // Function that takes a variable number of arguments // log(x[, base]) @@ -335,6 +371,9 @@ STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_isfinite), MP_ROM_PTR(&mp_math_isfinite_obj) }, { MP_ROM_QSTR(MP_QSTR_isinf), MP_ROM_PTR(&mp_math_isinf_obj) }, { MP_ROM_QSTR(MP_QSTR_isnan), MP_ROM_PTR(&mp_math_isnan_obj) }, + #if MICROPY_PY_MATH_ISCLOSE + { MP_ROM_QSTR(MP_QSTR_isclose), MP_ROM_PTR(&mp_math_isclose_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_trunc), MP_ROM_PTR(&mp_math_trunc_obj) }, { MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&mp_math_radians_obj) }, { MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&mp_math_degrees_obj) }, diff --git a/py/mpconfig.h b/py/mpconfig.h index bded9da9fcd22..a21a6c70752f1 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1079,6 +1079,11 @@ typedef double mp_float_t; #define MICROPY_PY_MATH_FACTORIAL (0) #endif +// Whether to provide math.isclose function +#ifndef MICROPY_PY_MATH_ISCLOSE +#define MICROPY_PY_MATH_ISCLOSE (0) +#endif + // Whether to provide "cmath" module #ifndef MICROPY_PY_CMATH #define MICROPY_PY_CMATH (0) diff --git a/tests/float/math_isclose.py b/tests/float/math_isclose.py new file mode 100644 index 0000000000000..13dfff75fbaa0 --- /dev/null +++ b/tests/float/math_isclose.py @@ -0,0 +1,47 @@ +# test math.isclose (appeared in Python 3.5) + +try: + from math import isclose +except ImportError: + print("SKIP") + raise SystemExit + +def test(a, b, **kwargs): + print(isclose(a, b, **kwargs)) + +def test_combinations(a, b, **kwargs): + test(a, a, **kwargs) + test(a, b, **kwargs) + test(b, a, **kwargs) + test(b, b, **kwargs) + +# Special numbers +test_combinations(float('nan'), 1) +test_combinations(float('inf'), 1) +test_combinations(float('-inf'), 1) + +# Equality +test(1.0, 1.0, rel_tol=0.0, abs_tol=0.0) +test(2.35e-100, 2.35e-100, rel_tol=0.0, abs_tol=0.0) +test(2.1234e100, 2.1234e100, rel_tol=0.0, abs_tol=0.0) + +# Relative tolerance +test(1000.0, 1001.0, rel_tol=1e-3) +test(1000.0, 1001.0, rel_tol=1e-4) +test(1000, 1001, rel_tol=1e-3) +test(1000, 1001, rel_tol=1e-4) +test_combinations(0, 1, rel_tol=1.0) + +# Absolute tolerance +test(0.0, 1e-10, abs_tol=1e-10, rel_tol=0.1) +test(0.0, 1e-10, abs_tol=0.0, rel_tol=0.1) + +# Bad parameters +try: + isclose(0, 0, abs_tol=-1) +except ValueError: + print('ValueError') +try: + isclose(0, 0, rel_tol=-1) +except ValueError: + print('ValueError') diff --git a/tests/float/math_isclose.py.exp b/tests/float/math_isclose.py.exp new file mode 100644 index 0000000000000..02974666c073a --- /dev/null +++ b/tests/float/math_isclose.py.exp @@ -0,0 +1,27 @@ +False +False +False +True +True +False +False +True +True +False +False +True +True +True +True +True +False +True +False +True +True +True +True +True +False +ValueError +ValueError From 0c80cb39af7a0f6b0ad73d38bf28a8fc1f50b3c7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Aug 2019 15:50:02 +1000 Subject: [PATCH 0346/1299] py: Introduce MP_UNREACHABLE macro to annotate unreachable code. And use it to replace the same pattern at the end of nlrthumb.c:nlr_jump. --- py/mpconfig.h | 9 +++++++++ py/nlrthumb.c | 6 +----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index a21a6c70752f1..e8f60bd77ffdc 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1527,6 +1527,15 @@ typedef double mp_float_t; #define MP_UNLIKELY(x) __builtin_expect((x), 0) #endif +// To annotate that code is unreachable +#ifndef MP_UNREACHABLE +#if defined(__GNUC__) +#define MP_UNREACHABLE __builtin_unreachable(); +#else +#define MP_UNREACHABLE for (;;); +#endif +#endif + #ifndef MP_HTOBE16 #if MP_ENDIANNESS_LITTLE # define MP_HTOBE16(x) ((uint16_t)( (((x) & 0xff) << 8) | (((x) >> 8) & 0xff) )) diff --git a/py/nlrthumb.c b/py/nlrthumb.c index eef05229d693f..bc30388278f56 100644 --- a/py/nlrthumb.c +++ b/py/nlrthumb.c @@ -135,11 +135,7 @@ NORETURN void nlr_jump(void *val) { : // clobbered registers ); - #if defined(__GNUC__) - __builtin_unreachable(); - #else - for (;;); // needed to silence compiler warning - #endif + MP_UNREACHABLE } #endif // MICROPY_NLR_THUMB From 11ecdf2ec699c5f78ef7b2bc1bd34618394cc9fa Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Aug 2019 15:51:40 +1000 Subject: [PATCH 0347/1299] py/nlr: Use MP_UNREACHABLE at the end of arch-specific nlr_jump funcs. Recent versions of gcc perform optimisations which can lead to the following code from the MP_NLR_JUMP_HEAD macro being omitted: top->ret_val = val; \ MP_NLR_RESTORE_PYSTACK(top); \ *_top_ptr = top->prev; \ This is noticeable (at least) in the unix coverage on x86-64 built with gcc 9.1.0. This is because the nlr_jump function is marked as no-return, so gcc deduces that the above code has no effect. Adding MP_UNREACHABLE tells the compiler that the asm code may branch elsewhere, and so it cannot optimise away the code. --- py/nlrx64.c | 2 +- py/nlrx86.c | 2 +- py/nlrxtensa.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/py/nlrx64.c b/py/nlrx64.c index a3a1cf341b916..95496b3805ddd 100644 --- a/py/nlrx64.c +++ b/py/nlrx64.c @@ -108,7 +108,7 @@ NORETURN void nlr_jump(void *val) { : // clobbered registers ); - for (;;); // needed to silence compiler warning + MP_UNREACHABLE } #endif // MICROPY_NLR_X64 diff --git a/py/nlrx86.c b/py/nlrx86.c index 59b97d8ee6a9a..6195db63cdda1 100644 --- a/py/nlrx86.c +++ b/py/nlrx86.c @@ -100,7 +100,7 @@ NORETURN void nlr_jump(void *val) { : // clobbered registers ); - for (;;); // needed to silence compiler warning + MP_UNREACHABLE } #endif // MICROPY_NLR_X86 diff --git a/py/nlrxtensa.c b/py/nlrxtensa.c index cd3dee364c23c..895b2029e8ab2 100644 --- a/py/nlrxtensa.c +++ b/py/nlrxtensa.c @@ -77,7 +77,7 @@ NORETURN void nlr_jump(void *val) { : // clobbered registers ); - for (;;); // needed to silence compiler warning + MP_UNREACHABLE } #endif // MICROPY_NLR_XTENSA From 3a679eaf00b909980ad38344ec0c7395adcd0564 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Sat, 17 Aug 2019 13:50:21 +0100 Subject: [PATCH 0348/1299] docs/reference/speed_python: Update that read-only buffers are accepted. As allowed by recent cd35dd9d9a29836906acdce60c931f6352b536d0 --- docs/reference/speed_python.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst index c5aa80c6e1841..f2d7739fb0a50 100644 --- a/docs/reference/speed_python.rst +++ b/docs/reference/speed_python.rst @@ -293,10 +293,12 @@ microseconds. The rules for casting are as follows: * The argument to a bool cast must be integral type (boolean or integer); when used as a return type the viper function will return True or False objects. * If the argument is a Python object and the cast is ``ptr``, ``ptr``, ``ptr16`` or ``ptr32``, - then the Python object must either have the buffer protocol with read-write capabilities - (in which case a pointer to the start of the buffer is returned) or it must be of integral - type (in which case the value of that integral object is returned). - + then the Python object must either have the buffer protocol (in which case a pointer to the + start of the buffer is returned) or it must be of integral type (in which case the value of + that integral object is returned). + +Writing to a pointer which points to a read-only object will lead to undefined behaviour. + The following example illustrates the use of a ``ptr16`` cast to toggle pin X1 ``n`` times: .. code:: python From 7d851a27f146188752e89bb026021fb8d3985395 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 17 Aug 2019 23:50:19 +1000 Subject: [PATCH 0349/1299] extmod/modure: Make regex dump-code debugging feature optional. Enabled via MICROPY_PY_URE_DEBUG, disabled by default (but enabled on unix coverage build). This is a rarely used feature that costs a lot of code (500-800 bytes flash). Debugging of regular expressions can be done offline with other tools. --- extmod/modure.c | 9 +++++++++ ports/unix/mpconfigport_coverage.h | 1 + py/mpconfig.h | 4 ++++ tests/extmod/ure_debug.py | 3 ++- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/extmod/modure.c b/extmod/modure.c index 0d5330cb548e4..8a60207053054 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -382,6 +382,7 @@ STATIC const mp_obj_type_t re_type = { }; STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { + (void)n_args; const char *re_str = mp_obj_str_get_str(args[0]); int size = re1_5_sizecode(re_str); if (size == -1) { @@ -389,18 +390,22 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { } mp_obj_re_t *o = m_new_obj_var(mp_obj_re_t, char, size); o->base.type = &re_type; + #if MICROPY_PY_URE_DEBUG int flags = 0; if (n_args > 1) { flags = mp_obj_get_int(args[1]); } + #endif int error = re1_5_compilecode(&o->re, re_str); if (error != 0) { error: mp_raise_ValueError("Error in regex"); } + #if MICROPY_PY_URE_DEBUG if (flags & FLAG_DEBUG) { re1_5_dumpcode(&o->re); } + #endif return MP_OBJ_FROM_PTR(o); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile); @@ -440,7 +445,9 @@ STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = { #if MICROPY_PY_URE_SUB { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&mod_re_sub_obj) }, #endif + #if MICROPY_PY_URE_DEBUG { MP_ROM_QSTR(MP_QSTR_DEBUG), MP_ROM_INT(FLAG_DEBUG) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table); @@ -455,7 +462,9 @@ const mp_obj_module_t mp_module_ure = { #define re1_5_fatal(x) assert(!x) #include "re1.5/compilecode.c" +#if MICROPY_PY_URE_DEBUG #include "re1.5/dumpcode.c" +#endif #include "re1.5/recursiveloop.c" #include "re1.5/charclass.c" diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index b2f1d6e88ea59..afd364649077c 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -50,6 +50,7 @@ #define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) #define MICROPY_PY_IO_BUFFEREDWRITER (1) #define MICROPY_PY_IO_RESOURCE_STREAM (1) +#define MICROPY_PY_URE_DEBUG (1) #define MICROPY_PY_URE_MATCH_GROUPS (1) #define MICROPY_PY_URE_MATCH_SPAN_START_END (1) #define MICROPY_PY_URE_SUB (1) diff --git a/py/mpconfig.h b/py/mpconfig.h index e8f60bd77ffdc..57dec3cf266b1 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1259,6 +1259,10 @@ typedef double mp_float_t; #define MICROPY_PY_URE (0) #endif +#ifndef MICROPY_PY_URE_DEBUG +#define MICROPY_PY_URE_DEBUG (0) +#endif + #ifndef MICROPY_PY_URE_MATCH_GROUPS #define MICROPY_PY_URE_MATCH_GROUPS (0) #endif diff --git a/tests/extmod/ure_debug.py b/tests/extmod/ure_debug.py index cfb264bb6d290..621fc8d50eace 100644 --- a/tests/extmod/ure_debug.py +++ b/tests/extmod/ure_debug.py @@ -1,7 +1,8 @@ # test printing debugging info when compiling try: import ure -except ImportError: + ure.DEBUG +except (ImportError, AttributeError): print("SKIP") raise SystemExit From ae6fe8b43c08abe215dde355e04e561ad2dd1808 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Mon, 19 Aug 2019 14:16:33 +0200 Subject: [PATCH 0350/1299] py/compile: Improve the line numbering precision for comprehensions. The line number for comprehensions is now always reported as the correct global location in the script, instead of just "line 1". --- py/compile.c | 3 +++ tests/cmdline/cmd_showbc.py.exp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/py/compile.c b/py/compile.c index 27b706c8fe044..c0ae3de1145ac 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3112,6 +3112,9 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { scope->num_pos_args = 1; } + // Set the source line number for the start of the comprehension + EMIT_ARG(set_source_line, pns->source_line); + if (scope->kind == SCOPE_LIST_COMP) { EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST); } else if (scope->kind == SCOPE_DICT_COMP) { diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 8d36b89df75d4..8d5d2ffe302ce 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -449,6 +449,7 @@ arg names: * * * (N_STATE 9) (N_EXC_STACK 0) bc=-\\d\+ line=1 + bc=0 line=59 00 LOAD_NULL 01 LOAD_FAST 2 02 LOAD_NULL @@ -471,6 +472,7 @@ arg names: * * * (N_STATE 10) (N_EXC_STACK 0) bc=-\\d\+ line=1 + bc=0 line=60 00 BUILD_LIST 0 02 LOAD_FAST 2 03 GET_ITER_STACK From 4ab5156c01bfd4a6304e26b1dc2d34163b8637c0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 17 Aug 2019 00:32:04 +1000 Subject: [PATCH 0351/1299] tools/mpy-tool.py: Force native func alignment to halfword/word on ARM. This is necessary for ARMV6 and V7. Without this change, calling a frozen native/viper function that is misaligned will crash. --- tools/mpy-tool.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 648d56fe057e9..7938ea5dc8480 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -471,6 +471,14 @@ def __init__(self, code_kind, fun_data, prelude_offset, prelude, qstr_links, qst else: self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",%progbits @ ")))' + # Allow single-byte alignment by default for x86/x64/xtensa, but on ARM we need halfword- or word- alignment. + if config.native_arch == MP_NATIVE_ARCH_ARMV6: + # ARMV6 -- four byte align. + self.fun_data_attributes += ' __attribute__ ((aligned (4)))' + elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: + # ARMVxxM -- two byte align. + self.fun_data_attributes += ' __attribute__ ((aligned (2)))' + def _asm_thumb_rewrite_mov(self, pc, val): print(' (%u & 0xf0) | (%s >> 12),' % (self.bytecode[pc], val), end='') print(' (%u & 0xfb) | (%s >> 9 & 0x04),' % (self.bytecode[pc + 1], val), end='') From 0bd1eb80ff49dd0d4ad0c369a83a5aadea995944 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 19 Aug 2019 10:59:27 +1000 Subject: [PATCH 0352/1299] qemu-arm: Add testing of frozen native modules. - Split 'qemu-arm' from 'unix' for generating tests. - Add frozen module to the qemu-arm test build. - Add test that reproduces the requirement to half-word align native function data. --- ports/qemu-arm/Makefile | 8 ++++++ ports/qemu-arm/Makefile.test | 7 +++-- .../test-frzmpy/native_frozen_align.py | 13 +++++++++ tests/qemu-arm/native_test.py | 5 ++++ tests/qemu-arm/native_test.py.exp | 3 +++ tests/run-tests | 27 ++++++++++++------- tools/tinytest-codegen.py | 4 ++- 7 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 ports/qemu-arm/test-frzmpy/native_frozen_align.py create mode 100644 tests/qemu-arm/native_test.py create mode 100644 tests/qemu-arm/native_test.py.exp diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 03a8afe77ea9b..c730c829757d4 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -114,6 +114,14 @@ OBJ = $(OBJ_COMMON) $(OBJ_RUN) $(OBJ_TEST) # List of sources for qstr extraction SRC_QSTR += $(SRC_COMMON_C) $(SRC_RUN_C) $(LIB_SRC_C) +ifneq ($(FROZEN_MPY_DIR),) +# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and +# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). +CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool +CFLAGS += -DMICROPY_MODULE_FROZEN_MPY +MPY_CROSS_FLAGS += -march=armv7m +endif + all: run run: $(BUILD)/firmware.elf diff --git a/ports/qemu-arm/Makefile.test b/ports/qemu-arm/Makefile.test index 347c2fefd3024..32ec95a4f3f86 100644 --- a/ports/qemu-arm/Makefile.test +++ b/ports/qemu-arm/Makefile.test @@ -1,5 +1,7 @@ LIB_SRC_C = lib/upytesthelper/upytesthelper.c +FROZEN_MPY_DIR ?= test-frzmpy + include Makefile CFLAGS += -DTEST @@ -8,7 +10,7 @@ CFLAGS += -DTEST $(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h $(BUILD)/genhdr/tests.h: - (cd $(TOP)/tests; ./run-tests --write-exp) + (cd $(TOP)/tests; ./run-tests --target=qemu-arm --write-exp) $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py) > $@ $(BUILD)/tinytest.o: @@ -18,7 +20,8 @@ $(BUILD)/firmware-test.elf: $(OBJ_COMMON) $(OBJ_TEST) $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ +# Note: Using timeout(1) to handle cases where qemu hangs (e.g. this can happen with alignment errors). test: $(BUILD)/firmware-test.elf - qemu-system-arm -machine $(BOARD) $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< > $(BUILD)/console.out + timeout --foreground -k 5s 30s qemu-system-arm -machine $(BOARD) $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< > $(BUILD)/console.out $(Q)tail -n2 $(BUILD)/console.out $(Q)tail -n1 $(BUILD)/console.out | grep -q "status: 0" diff --git a/ports/qemu-arm/test-frzmpy/native_frozen_align.py b/ports/qemu-arm/test-frzmpy/native_frozen_align.py new file mode 100644 index 0000000000000..5c5c0e8d23ca4 --- /dev/null +++ b/ports/qemu-arm/test-frzmpy/native_frozen_align.py @@ -0,0 +1,13 @@ +import micropython + +@micropython.native +def native_x(x): + print(x + 1) + +@micropython.native +def native_y(x): + print(x + 1) + +@micropython.native +def native_z(x): + print(x + 1) diff --git a/tests/qemu-arm/native_test.py b/tests/qemu-arm/native_test.py new file mode 100644 index 0000000000000..0b58433d92026 --- /dev/null +++ b/tests/qemu-arm/native_test.py @@ -0,0 +1,5 @@ +import native_frozen_align + +native_frozen_align.native_x(1) +native_frozen_align.native_y(2) +native_frozen_align.native_z(3) diff --git a/tests/qemu-arm/native_test.py.exp b/tests/qemu-arm/native_test.py.exp new file mode 100644 index 0000000000000..dcf37cd5e2620 --- /dev/null +++ b/tests/qemu-arm/native_test.py.exp @@ -0,0 +1,3 @@ +2 +3 +4 diff --git a/tests/run-tests b/tests/run-tests index 9f74c1cfcc47b..c45d2787e2f98 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -349,6 +349,8 @@ def run_tests(pyb, tests, args, base_path="."): for t in tests: if t.startswith('basics/io_'): skip_tests.add(t) + elif args.target == 'qemu-arm': + skip_tests.add('misc/print_exception.py') # requires sys stdfiles # Some tests are known to fail on 64-bit machines if pyb is None and platform.architecture()[0] == '64bit': @@ -527,8 +529,9 @@ the last matching regex is used: cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() + LOCAL_TARGETS = ('unix', 'qemu-arm',) EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266', 'esp32', 'minimal', 'nrf') - if args.target == 'unix' or args.list_tests: + if args.target in LOCAL_TARGETS or args.list_tests: pyb = None elif args.target in EXTERNAL_TARGETS: global pyboard @@ -537,24 +540,28 @@ the last matching regex is used: pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password) pyb.enter_raw_repl() else: - raise ValueError('target must be either %s or unix' % ", ".join(EXTERNAL_TARGETS)) + raise ValueError('target must be one of %s' % ", ".join(LOCAL_TARGETS + EXTERNAL_TARGETS)) if len(args.files) == 0: if args.test_dirs is None: + test_dirs = ('basics', 'micropython', 'misc', 'extmod',) if args.target == 'pyboard': # run pyboard tests - test_dirs = ('basics', 'micropython', 'float', 'misc', 'stress', 'extmod', 'pyb', 'pybnative', 'inlineasm') + test_dirs += ('float', 'stress', 'pyb', 'pybnative', 'inlineasm') elif args.target in ('esp8266', 'esp32', 'minimal', 'nrf'): - test_dirs = ('basics', 'micropython', 'float', 'misc', 'extmod') + test_dirs += ('float',) elif args.target == 'wipy': # run WiPy tests - test_dirs = ('basics', 'micropython', 'misc', 'extmod', 'wipy') - else: + test_dirs += ('wipy',) + elif args.target == 'unix': # run PC tests - test_dirs = ( - 'basics', 'micropython', 'float', 'import', 'io', 'misc', - 'stress', 'unicode', 'extmod', 'unix', 'cmdline', - ) + test_dirs += ('float', 'import', 'io', 'stress', 'unicode', 'unix', 'cmdline',) + elif args.target == 'qemu-arm': + if not args.write_exp: + raise ValueError('--target=qemu-arm must be used with --write-exp') + # Generate expected output files for qemu run. + # This list should match the test_dirs tuple in tinytest-codegen.py. + test_dirs += ('float', 'inlineasm', 'qemu-arm',) else: # run tests from these directories test_dirs = args.test_dirs diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index ad3b3bbec9508..bdace1c8b5a83 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -54,7 +54,7 @@ def script_to_map(test_file): ## XXX: may be we could have `--without ` argument... # currently these tests are selected because they pass on qemu-arm -test_dirs = ('basics', 'micropython', 'float', 'extmod', 'inlineasm') # 'import', 'io', 'misc') +test_dirs = ('basics', 'micropython', 'misc', 'extmod', 'float', 'inlineasm', 'qemu-arm',) # 'import', 'io',) exclude_tests = ( # pattern matching in .exp 'basics/bytes_compare3.py', @@ -81,6 +81,8 @@ def script_to_map(test_file): 'micropython/heapalloc_traceback.py', # pattern matching in .exp 'micropython/meminfo.py', + # needs sys stdfiles + 'misc/print_exception.py', ) output = [] From 3327dfc16edf5110370c53de38bb4941a12928a3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Aug 2019 22:29:24 +1000 Subject: [PATCH 0353/1299] extmod/moducryptolib: Use "static" not "STATIC" for inline functions. --- extmod/moducryptolib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c index 15cd4535f8fe6..fd487a816c738 100644 --- a/extmod/moducryptolib.c +++ b/extmod/moducryptolib.c @@ -89,7 +89,7 @@ typedef struct _mp_obj_aes_t { uint8_t key_type: 2; } mp_obj_aes_t; -STATIC inline bool is_ctr_mode(int block_mode) { +static inline bool is_ctr_mode(int block_mode) { #if MICROPY_PY_UCRYPTOLIB_CTR return block_mode == UCRYPTOLIB_MODE_CTR; #else @@ -97,7 +97,7 @@ STATIC inline bool is_ctr_mode(int block_mode) { #endif } -STATIC inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) { +static inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) { // ctr_params follows aes object struct return (struct ctr_params*)&o[1]; } From 0cc8910bc58c1a1f69a696f5efe4ccf0ffcf2984 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Aug 2019 22:29:53 +1000 Subject: [PATCH 0354/1299] extmod: Give vars/funcs unique names so STATIC can be set to nothing. Fixes issue #5018. --- extmod/moduheapq.c | 20 ++++++++++---------- extmod/modussl_axtls.c | 26 +++++++++++++------------- extmod/modutimeq.c | 20 ++++++++++---------- extmod/vfs_fat_file.c | 16 ++++++++-------- extmod/vfs_posix_file.c | 16 ++++++++-------- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c index bdaf191e9471e..1574eb8627a77 100644 --- a/extmod/moduheapq.c +++ b/extmod/moduheapq.c @@ -31,14 +31,14 @@ // the algorithm here is modelled on CPython's heapq.py -STATIC mp_obj_list_t *get_heap(mp_obj_t heap_in) { +STATIC mp_obj_list_t *uheapq_get_heap(mp_obj_t heap_in) { if (!mp_obj_is_type(heap_in, &mp_type_list)) { mp_raise_TypeError("heap must be a list"); } return MP_OBJ_TO_PTR(heap_in); } -STATIC void heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) { +STATIC void uheapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) { mp_obj_t item = heap->items[pos]; while (pos > start_pos) { mp_uint_t parent_pos = (pos - 1) >> 1; @@ -53,7 +53,7 @@ STATIC void heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t po heap->items[pos] = item; } -STATIC void heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) { +STATIC void uheapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) { mp_uint_t start_pos = pos; mp_uint_t end_pos = heap->len; mp_obj_t item = heap->items[pos]; @@ -67,19 +67,19 @@ STATIC void heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) { pos = child_pos; } heap->items[pos] = item; - heap_siftdown(heap, start_pos, pos); + uheapq_heap_siftdown(heap, start_pos, pos); } STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) { - mp_obj_list_t *heap = get_heap(heap_in); + mp_obj_list_t *heap = uheapq_get_heap(heap_in); mp_obj_list_append(heap_in, item); - heap_siftdown(heap, 0, heap->len - 1); + uheapq_heap_siftdown(heap, 0, heap->len - 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush); STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) { - mp_obj_list_t *heap = get_heap(heap_in); + mp_obj_list_t *heap = uheapq_get_heap(heap_in); if (heap->len == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); } @@ -88,16 +88,16 @@ STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) { heap->items[0] = heap->items[heap->len]; heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer if (heap->len) { - heap_siftup(heap, 0); + uheapq_heap_siftup(heap, 0); } return item; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop); STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) { - mp_obj_list_t *heap = get_heap(heap_in); + mp_obj_list_t *heap = uheapq_get_heap(heap_in); for (mp_uint_t i = heap->len / 2; i > 0;) { - heap_siftup(heap, --i); + uheapq_heap_siftup(heap, --i); } return mp_const_none; } diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index b559b1358002e..2ea175728728f 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -54,7 +54,7 @@ struct ssl_args { STATIC const mp_obj_type_t ussl_socket_type; -STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { +STATIC mp_obj_ssl_socket_t *ussl_socket_new(mp_obj_t sock, struct ssl_args *args) { #if MICROPY_PY_USSL_FINALISER mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t); #else @@ -118,13 +118,13 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { return o; } -STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +STATIC void ussl_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "<_SSLSocket %p>", self->ssl_sock); } -STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t ussl_socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); if (o->ssl_sock == NULL) { @@ -173,7 +173,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc return size; } -STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { +STATIC mp_uint_t ussl_socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); if (o->ssl_sock == NULL) { @@ -189,7 +189,7 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in return r; } -STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { +STATIC mp_uint_t ussl_socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in); if (request == MP_STREAM_CLOSE && self->ssl_sock != NULL) { ssl_free(self->ssl_sock); @@ -200,7 +200,7 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode); } -STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { +STATIC mp_obj_t ussl_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in); mp_obj_t sock = o->sock; mp_obj_t dest[3]; @@ -210,14 +210,14 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { o->blocking = mp_obj_is_true(flag_in); return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(ussl_socket_setblocking_obj, ussl_socket_setblocking); STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, + { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&ussl_socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, #if MICROPY_PY_USSL_FINALISER { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, @@ -227,16 +227,16 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table); STATIC const mp_stream_p_t ussl_socket_stream_p = { - .read = socket_read, - .write = socket_write, - .ioctl = socket_ioctl, + .read = ussl_socket_read, + .write = ussl_socket_write, + .ioctl = ussl_socket_ioctl, }; STATIC const mp_obj_type_t ussl_socket_type = { { &mp_type_type }, // Save on qstr's, reuse same as for module .name = MP_QSTR_ussl, - .print = socket_print, + .print = ussl_socket_print, .getiter = NULL, .iternext = NULL, .protocol = &ussl_socket_stream_p, @@ -260,7 +260,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); - return MP_OBJ_FROM_PTR(socket_new(sock, &args)); + return MP_OBJ_FROM_PTR(ussl_socket_new(sock, &args)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket); diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c index 26f5a78fae00a..28a2a70c5ec79 100644 --- a/extmod/modutimeq.c +++ b/extmod/modutimeq.c @@ -55,7 +55,7 @@ typedef struct _mp_obj_utimeq_t { STATIC mp_uint_t utimeq_id; -STATIC mp_obj_utimeq_t *get_heap(mp_obj_t heap_in) { +STATIC mp_obj_utimeq_t *utimeq_get_heap(mp_obj_t heap_in) { return MP_OBJ_TO_PTR(heap_in); } @@ -85,7 +85,7 @@ STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t return MP_OBJ_FROM_PTR(o); } -STATIC void heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) { +STATIC void utimeq_heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) { struct qentry item = heap->items[pos]; while (pos > start_pos) { mp_uint_t parent_pos = (pos - 1) >> 1; @@ -101,7 +101,7 @@ STATIC void heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t heap->items[pos] = item; } -STATIC void heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) { +STATIC void utimeq_heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) { mp_uint_t start_pos = pos; mp_uint_t end_pos = heap->len; struct qentry item = heap->items[pos]; @@ -118,13 +118,13 @@ STATIC void heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) { pos = child_pos; } heap->items[pos] = item; - heap_siftdown(heap, start_pos, pos); + utimeq_heap_siftdown(heap, start_pos, pos); } STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_t heap_in = args[0]; - mp_obj_utimeq_t *heap = get_heap(heap_in); + mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == heap->alloc) { mp_raise_msg(&mp_type_IndexError, "queue overflow"); } @@ -133,14 +133,14 @@ STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) { heap->items[l].id = utimeq_id++; heap->items[l].callback = args[2]; heap->items[l].args = args[3]; - heap_siftdown(heap, 0, heap->len); + utimeq_heap_siftdown(heap, 0, heap->len); heap->len++; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_heappush_obj, 4, 4, mod_utimeq_heappush); STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) { - mp_obj_utimeq_t *heap = get_heap(heap_in); + mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); } @@ -158,14 +158,14 @@ STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) { heap->items[heap->len].callback = MP_OBJ_NULL; // so we don't retain a pointer heap->items[heap->len].args = MP_OBJ_NULL; if (heap->len) { - heap_siftup(heap, 0); + utimeq_heap_siftup(heap, 0); } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop); STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) { - mp_obj_utimeq_t *heap = get_heap(heap_in); + mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); } @@ -177,7 +177,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_peektime_obj, mod_utimeq_peektime); #if DEBUG STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) { - mp_obj_utimeq_t *heap = get_heap(heap_in); + mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); for (int i = 0; i < heap->len; i++) { printf(UINT_FMT "\t%p\t%p\n", heap->items[i].time, MP_OBJ_TO_PTR(heap->items[i].callback), MP_OBJ_TO_PTR(heap->items[i].args)); diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index f7b9331b82e0a..fb1e582f27f9c 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -219,7 +219,7 @@ STATIC mp_obj_t file_obj_make_new(const mp_obj_type_t *type, size_t n_args, size // TODO gc hook to close the file if not already closed -STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { +STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, @@ -234,10 +234,10 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO -STATIC const mp_stream_p_t fileio_stream_p = { +STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, @@ -250,12 +250,12 @@ const mp_obj_type_t mp_type_vfs_fat_fileio = { .make_new = file_obj_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, - .protocol = &fileio_stream_p, - .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, + .protocol = &vfs_fat_fileio_stream_p, + .locals_dict = (mp_obj_dict_t*)&vfs_fat_rawfile_locals_dict, }; #endif -STATIC const mp_stream_p_t textio_stream_p = { +STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, @@ -269,8 +269,8 @@ const mp_obj_type_t mp_type_vfs_fat_textio = { .make_new = file_obj_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, - .protocol = &textio_stream_p, - .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, + .protocol = &vfs_fat_textio_stream_p, + .locals_dict = (mp_obj_dict_t*)&vfs_fat_rawfile_locals_dict, }; // Factory function for I/O stream classes diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 44cb85dcc7613..6f7ce814f3a42 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -200,7 +200,7 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ } } -STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { +STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&vfs_posix_file_fileno_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, @@ -215,10 +215,10 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO -STATIC const mp_stream_p_t fileio_stream_p = { +STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = { .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, @@ -231,12 +231,12 @@ const mp_obj_type_t mp_type_vfs_posix_fileio = { .make_new = vfs_posix_file_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, - .protocol = &fileio_stream_p, - .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, + .protocol = &vfs_posix_fileio_stream_p, + .locals_dict = (mp_obj_dict_t*)&vfs_posix_rawfile_locals_dict, }; #endif -STATIC const mp_stream_p_t textio_stream_p = { +STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, @@ -250,8 +250,8 @@ const mp_obj_type_t mp_type_vfs_posix_textio = { .make_new = vfs_posix_file_make_new, .getiter = mp_identity_getiter, .iternext = mp_stream_unbuffered_iter, - .protocol = &textio_stream_p, - .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict, + .protocol = &vfs_posix_textio_stream_p, + .locals_dict = (mp_obj_dict_t*)&vfs_posix_rawfile_locals_dict, }; const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_textio}, STDIN_FILENO}; From 05eb897d06cc4da04dd96f3b661b617b98cb6800 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 9 Jul 2019 15:08:52 +1000 Subject: [PATCH 0355/1299] esp32: Add esp32.Partition class to expose partition and OTA funcs. Partitions are exposed as a standard MicroPython block device. --- docs/library/esp32.rst | 45 +++++++ ports/esp32/Makefile | 7 ++ ports/esp32/esp32_partition.c | 223 ++++++++++++++++++++++++++++++++++ ports/esp32/modesp32.c | 1 + ports/esp32/modesp32.h | 1 + 5 files changed, 277 insertions(+) create mode 100644 ports/esp32/esp32_partition.c diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index c934ef0954872..a593965ae2740 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -36,6 +36,51 @@ Functions Read the raw value of the internal Hall sensor, returning an integer. +Flash partitions +---------------- + +This class gives access to the partitions in the device's flash memory. + +.. class:: Partition(id) + + Create an object representing a partition. *id* can be a string which is the label + of the partition to retrieve, or one of the constants: ``BOOT`` or ``RUNNING``. + +.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None) + + Find a partition specified by *type*, *subtype* and *label*. Returns a + (possibly empty) list of Partition objects. + +.. method:: Partition.info() + + Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``. + +.. method:: Partition.readblocks(block_num, buf) +.. method:: Partition.writeblocks(block_num, buf) +.. method:: Partition.ioctl(cmd, arg) + + These methods implement the block protocol defined by :class:`uos.AbstractBlockDev`. + +.. method:: Partition.set_boot() + + Sets the partition as the boot partition. + +.. method:: Partition.get_next_update() + + Gets the next update partition after this one, and returns a new Partition object. + +Constants +~~~~~~~~~ + +.. data:: Partition.BOOT + Partition.RUNNING + + Used in the `Partition` constructor to fetch various partitions. + +.. data:: Partition.TYPE_APP + Partition.TYPE_DATA + + Used in `Partition.find` to specify the partition type. The Ultra-Low-Power co-processor -------------------------------- diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 3802c2fc9c8d4..06cb553f4d1a2 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -128,6 +128,7 @@ INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include INC_ESPCOMP += -I$(ESPCOMP)/mdns/include INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include +INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include INC_ESPCOMP += -I$(ESPCOMP)/ulp/include INC_ESPCOMP += -I$(ESPCOMP)/vfs/include @@ -216,6 +217,7 @@ SRC_C = \ network_ppp.c \ modsocket.c \ modesp.c \ + esp32_partition.c \ esp32_ulp.c \ modesp32.c \ espneopixel.c \ @@ -288,6 +290,10 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard. ################################################################################ # List of object files from the ESP32 IDF components +ESPIDF_BOOTLOADER_SUPPORT_O = $(subst .c,.o,\ + $(filter-out $(ESPCOMP)/bootloader_support/src/bootloader_init.c,\ + $(wildcard $(ESPCOMP)/bootloader_support/src/*.c))) + ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) ESPIDF_EFUSE_O = $(patsubst %.c,%.o,\ @@ -399,6 +405,7 @@ $(BUILD_ESPIDF_LIB)/$(1)/lib$(1).a: $(addprefix $$(BUILD)/,$(2)) $(Q)$(AR) cru $$@ $$^ endef +$(eval $(call gen_espidf_lib_rule,bootloader_support,$(ESPIDF_BOOTLOADER_SUPPORT_O))) $(eval $(call gen_espidf_lib_rule,driver,$(ESPIDF_DRIVER_O))) $(eval $(call gen_espidf_lib_rule,efuse,$(ESPIDF_EFUSE_O))) $(eval $(call gen_espidf_lib_rule,esp32,$(ESPIDF_ESP32_O))) diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c new file mode 100644 index 0000000000000..49bb0632e3986 --- /dev/null +++ b/ports/esp32/esp32_partition.c @@ -0,0 +1,223 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "extmod/vfs.h" +#include "modesp32.h" +#include "esp_ota_ops.h" + +// esp_partition_read and esp_partition_write can operate on arbitrary bytes +// but esp_partition_erase_range operates on 4k blocks. But to make a partition +// implement the standard block protocol all operations are done on 4k blocks. +#define BLOCK_SIZE_BYTES (4096) + +enum { + ESP32_PARTITION_BOOT, + ESP32_PARTITION_RUNNING, +}; + +typedef struct _esp32_partition_obj_t { + mp_obj_base_t base; + const esp_partition_t *part; +} esp32_partition_obj_t; + +static inline void check_esp_err(esp_err_t e) { + if (e != ESP_OK) { + mp_raise_OSError(-e); + } +} + +STATIC esp32_partition_obj_t *esp32_partition_new(const esp_partition_t *part) { + if (part == NULL) { + mp_raise_OSError(MP_ENOENT); + } + esp32_partition_obj_t *self = m_new_obj(esp32_partition_obj_t); + self->base.type = &esp32_partition_type; + self->part = part; + return self; +} + +STATIC void esp32_partition_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "", + self->part->type, self->part->subtype, + self->part->address, self->part->size, + &self->part->label[0], self->part->encrypted + ); +} + +STATIC mp_obj_t esp32_partition_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // Check args + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + // Get requested partition + const esp_partition_t *part; + if (mp_obj_is_int(all_args[0])) { + // Integer given, get that particular partition + switch (mp_obj_get_int(all_args[0])) { + case ESP32_PARTITION_BOOT: + part = esp_ota_get_boot_partition(); + break; + case ESP32_PARTITION_RUNNING: + part = esp_ota_get_running_partition(); + break; + default: + mp_raise_ValueError(NULL); + } + } else { + // String given, search for partition with that label + const char *label = mp_obj_str_get_str(all_args[0]); + part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, label); + if (part == NULL) { + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, label); + } + } + + // Return new object + return MP_OBJ_FROM_PTR(esp32_partition_new(part)); +} + +STATIC mp_obj_t esp32_partition_find(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + // Parse args + enum { ARG_type, ARG_subtype, ARG_label }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_type, MP_ARG_INT, {.u_int = ESP_PARTITION_TYPE_APP} }, + { MP_QSTR_subtype, MP_ARG_INT, {.u_int = ESP_PARTITION_SUBTYPE_ANY} }, + { MP_QSTR_label, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Get optional label string + const char *label = NULL; + if (args[ARG_label].u_obj != mp_const_none) { + label = mp_obj_str_get_str(args[ARG_label].u_obj); + } + + // Build list of matching partitions + mp_obj_t list = mp_obj_new_list(0, NULL); + esp_partition_iterator_t iter = esp_partition_find(args[ARG_type].u_int, args[ARG_subtype].u_int, label); + while (iter != NULL) { + mp_obj_list_append(list, MP_OBJ_FROM_PTR(esp32_partition_new(esp_partition_get(iter)))); + iter = esp_partition_next(iter); + } + esp_partition_iterator_release(iter); + + return list; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_partition_find_fun_obj, 0, esp32_partition_find); +STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(esp32_partition_find_obj, MP_ROM_PTR(&esp32_partition_find_fun_obj)); + +STATIC mp_obj_t esp32_partition_info(mp_obj_t self_in) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t tuple[] = { + MP_OBJ_NEW_SMALL_INT(self->part->type), + MP_OBJ_NEW_SMALL_INT(self->part->subtype), + mp_obj_new_int_from_uint(self->part->address), + mp_obj_new_int_from_uint(self->part->size), + mp_obj_new_str(&self->part->label[0], strlen(&self->part->label[0])), + mp_obj_new_bool(self->part->encrypted), + }; + return mp_obj_new_tuple(6, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_info_obj, esp32_partition_info); + +STATIC mp_obj_t esp32_partition_readblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf_in) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint32_t offset = mp_obj_get_int(block_num) * BLOCK_SIZE_BYTES; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + check_esp_err(esp_partition_read(self->part, offset, bufinfo.buf, bufinfo.len)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_partition_readblocks_obj, esp32_partition_readblocks); + +STATIC mp_obj_t esp32_partition_writeblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf_in) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint32_t offset = mp_obj_get_int(block_num) * BLOCK_SIZE_BYTES; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + check_esp_err(esp_partition_erase_range(self->part, offset, bufinfo.len)); + check_esp_err(esp_partition_write(self->part, offset, bufinfo.buf, bufinfo.len)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_partition_writeblocks_obj, esp32_partition_writeblocks); + +STATIC mp_obj_t esp32_partition_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t cmd = mp_obj_get_int(cmd_in); + switch (cmd) { + case BP_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_DEINIT: return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_SYNC: return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(self->part->size / BLOCK_SIZE_BYTES); + case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(BLOCK_SIZE_BYTES); + default: return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_partition_ioctl_obj, esp32_partition_ioctl); + +STATIC mp_obj_t esp32_partition_set_boot(mp_obj_t self_in) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + esp_ota_set_boot_partition(self->part); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_set_boot_obj, esp32_partition_set_boot); + +STATIC mp_obj_t esp32_partition_get_next_update(mp_obj_t self_in) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_FROM_PTR(esp32_partition_new(esp_ota_get_next_update_partition(self->part))); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_get_next_update_obj, esp32_partition_get_next_update); + +STATIC const mp_rom_map_elem_t esp32_partition_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&esp32_partition_find_obj) }, + + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&esp32_partition_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&esp32_partition_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&esp32_partition_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&esp32_partition_ioctl_obj) }, + + { MP_ROM_QSTR(MP_QSTR_set_boot), MP_ROM_PTR(&esp32_partition_set_boot_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_next_update), MP_ROM_PTR(&esp32_partition_get_next_update_obj) }, + + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_INT(ESP32_PARTITION_BOOT) }, + { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(ESP32_PARTITION_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_TYPE_APP), MP_ROM_INT(ESP_PARTITION_TYPE_APP) }, + { MP_ROM_QSTR(MP_QSTR_TYPE_DATA), MP_ROM_INT(ESP_PARTITION_TYPE_DATA) }, +}; +STATIC MP_DEFINE_CONST_DICT(esp32_partition_locals_dict, esp32_partition_locals_dict_table); + +const mp_obj_type_t esp32_partition_type = { + { &mp_type_type }, + .name = MP_QSTR_Partition, + .print = esp32_partition_print, + .make_new = esp32_partition_make_new, + .locals_dict = (mp_obj_dict_t*)&esp32_partition_locals_dict, +}; diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c index 2e2d8236cf234..ada88116760f1 100644 --- a/ports/esp32/modesp32.c +++ b/ports/esp32/modesp32.c @@ -154,6 +154,7 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_raw_temperature), MP_ROM_PTR(&esp32_raw_temperature_obj) }, { MP_ROM_QSTR(MP_QSTR_hall_sensor), MP_ROM_PTR(&esp32_hall_sensor_obj) }, + { MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) }, { MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) }, { MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_PTR(&mp_const_false_obj) }, diff --git a/ports/esp32/modesp32.h b/ports/esp32/modesp32.h index 1d18cb41fbe53..26eec8ae69cea 100644 --- a/ports/esp32/modesp32.h +++ b/ports/esp32/modesp32.h @@ -26,6 +26,7 @@ #define RTC_LAST_EXT_PIN 39 #define RTC_IS_VALID_EXT_PIN(pin_id) ((1ll << (pin_id)) & RTC_VALID_EXT_PINS) +extern const mp_obj_type_t esp32_partition_type; extern const mp_obj_type_t esp32_ulp_type; #endif // MICROPY_INCLUDED_ESP32_MODESP32_H From fe3c064d42daeb02ee9a6ac91f657d397c0a20fa Mon Sep 17 00:00:00 2001 From: roland van straten Date: Fri, 16 Aug 2019 10:29:39 +0200 Subject: [PATCH 0356/1299] samd: Add minimum config for Atmel SAMD21-XPLAINED-PRO board. --- ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h | 2 ++ ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h create mode 100644 ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h new file mode 100644 index 0000000000000..c69b5b4c149de --- /dev/null +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "SAMD21-XPLAINED-PRO" +#define MICROPY_HW_MCU_NAME "SAMD21J18A" diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk new file mode 100644 index 0000000000000..f95c6549381ba --- /dev/null +++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.mk @@ -0,0 +1,4 @@ +MCU_SERIES = SAMD21 +CMSIS_MCU = SAMD21J18A +LD_FILES = boards/samd21x18a.ld sections.ld +TEXT0 = 0x2000 From 96ace8082e409c582911239ee913a95d955058bf Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 21 Aug 2019 21:16:40 +1000 Subject: [PATCH 0357/1299] esp8266/machine_uart: Allow remapping UART TX/RX pins from 1/3 to 15/13. Via the standard tx/rx arguments: UART(0, 115200, tx=Pin(15), rx=Pin(13)). Resolves issue #4718. --- ports/esp8266/machine_uart.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c index 21336c7fd4343..9aaa160922f10 100644 --- a/ports/esp8266/machine_uart.c +++ b/ports/esp8266/machine_uart.c @@ -29,11 +29,13 @@ #include #include "ets_sys.h" +#include "user_interface.h" #include "uart.h" #include "py/runtime.h" #include "py/stream.h" #include "py/mperrno.h" +#include "py/mphal.h" #include "modmachine.h" // UartDev is defined and initialized in rom code. @@ -63,14 +65,14 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k } STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_rxbuf, ARG_timeout, ARG_timeout_char }; + enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rxbuf, ARG_timeout, ARG_timeout_char }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = 0} }, - //{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - //{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, @@ -128,6 +130,22 @@ STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_o } } + // set tx/rx pins + mp_hal_pin_obj_t tx = 1, rx = 3; + if (args[ARG_tx].u_obj != MP_OBJ_NULL) { + tx = mp_hal_get_pin_obj(args[ARG_tx].u_obj); + } + if (args[ARG_rx].u_obj != MP_OBJ_NULL) { + rx = mp_hal_get_pin_obj(args[ARG_rx].u_obj); + } + if (tx == 1 && rx == 3) { + system_uart_de_swap(); + } else if (tx == 15 && rx == 13) { + system_uart_swap(); + } else { + mp_raise_ValueError("invalid tx/rx"); + } + // set stop bits switch (args[ARG_stop].u_int) { case 0: From 3d9bd80447c0834fae6746d45a0b45b3eb9cda6c Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 14:36:27 +1000 Subject: [PATCH 0358/1299] py/emitbc: Rewrite switch in load_const_tok to reduce code size. --- py/emitbc.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/py/emitbc.c b/py/emitbc.c index 35eb6df9c0c38..bb05169da3a7f 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -524,15 +524,13 @@ void mp_emit_bc_import(emit_t *emit, qstr qst, int kind) { } void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) { + MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_NONE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_NONE); + MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_TRUE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_TRUE); emit_bc_pre(emit, 1); - switch (tok) { - case MP_TOKEN_KW_FALSE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_FALSE); break; - case MP_TOKEN_KW_NONE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_NONE); break; - case MP_TOKEN_KW_TRUE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_TRUE); break; - default: - assert(tok == MP_TOKEN_ELLIPSIS); - emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); - break; + if (tok == MP_TOKEN_ELLIPSIS) { + emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); + } else { + emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_FALSE + (tok - MP_TOKEN_KW_FALSE)); } } From 8e7745eb315cdaf7dec033891f88e091ab4e016e Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 14:55:16 +1000 Subject: [PATCH 0359/1299] py/emitbc: Make all emit_write_bytecode_* funcs take a stack_adj arg. This factoring of code gives significant code-size savings: bare-arm: -456 -0.682% minimal x86: -844 -0.547% unix x64: -472 -0.095% unix nanbox: -1348 -0.303% stm32: -472 -0.130% PYBV10 cc3200: -448 -0.242% esp8266: -708 -0.108% esp32: -400 -0.036% GENERIC nrf: -520 -0.356% pca10040 samd: -456 -0.448% ADAFRUIT_ITSYBITSY_M4_EXPRESS --- py/emitbc.c | 266 ++++++++++++++++++++++------------------------------ 1 file changed, 111 insertions(+), 155 deletions(-) diff --git a/py/emitbc.c b/py/emitbc.c index bb05169da3a7f..fcbd979d27542 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -182,20 +182,27 @@ STATIC byte *emit_get_cur_to_write_bytecode(emit_t *emit, int num_bytes_to_write } } -STATIC void emit_write_bytecode_byte(emit_t *emit, byte b1) { +STATIC void emit_write_bytecode_raw_byte(emit_t *emit, byte b1) { byte *c = emit_get_cur_to_write_bytecode(emit, 1); c[0] = b1; } -STATIC void emit_write_bytecode_byte_byte(emit_t* emit, byte b1, byte b2) { +STATIC void emit_write_bytecode_byte(emit_t *emit, int stack_adj, byte b1) { + mp_emit_bc_adjust_stack_size(emit, stack_adj); + byte *c = emit_get_cur_to_write_bytecode(emit, 1); + c[0] = b1; +} + +STATIC void emit_write_bytecode_byte_byte(emit_t* emit, int stack_adj, byte b1, byte b2) { + mp_emit_bc_adjust_stack_size(emit, stack_adj); byte *c = emit_get_cur_to_write_bytecode(emit, 2); c[0] = b1; c[1] = b2; } // Similar to emit_write_bytecode_uint(), just some extra handling to encode sign -STATIC void emit_write_bytecode_byte_int(emit_t *emit, byte b1, mp_int_t num) { - emit_write_bytecode_byte(emit, b1); +STATIC void emit_write_bytecode_byte_int(emit_t *emit, int stack_adj, byte b1, mp_int_t num) { + emit_write_bytecode_byte(emit, stack_adj, b1); // We store each 7 bits in a separate byte, and that's how many bytes needed byte buf[BYTES_FOR_INT]; @@ -220,40 +227,41 @@ STATIC void emit_write_bytecode_byte_int(emit_t *emit, byte b1, mp_int_t num) { *c = *p; } -STATIC void emit_write_bytecode_byte_uint(emit_t *emit, byte b, mp_uint_t val) { - emit_write_bytecode_byte(emit, b); +STATIC void emit_write_bytecode_byte_uint(emit_t *emit, int stack_adj, byte b, mp_uint_t val) { + emit_write_bytecode_byte(emit, stack_adj, b); emit_write_uint(emit, emit_get_cur_to_write_bytecode, val); } #if MICROPY_PERSISTENT_CODE -STATIC void emit_write_bytecode_byte_const(emit_t *emit, byte b, mp_uint_t n, mp_uint_t c) { +STATIC void emit_write_bytecode_byte_const(emit_t *emit, int stack_adj, byte b, mp_uint_t n, mp_uint_t c) { if (emit->pass == MP_PASS_EMIT) { emit->const_table[n] = c; } - emit_write_bytecode_byte_uint(emit, b, n); + emit_write_bytecode_byte_uint(emit, stack_adj, b, n); } #endif -STATIC void emit_write_bytecode_byte_qstr(emit_t* emit, byte b, qstr qst) { +STATIC void emit_write_bytecode_byte_qstr(emit_t* emit, int stack_adj, byte b, qstr qst) { #if MICROPY_PERSISTENT_CODE assert((qst >> 16) == 0); + mp_emit_bc_adjust_stack_size(emit, stack_adj); byte *c = emit_get_cur_to_write_bytecode(emit, 3); c[0] = b; c[1] = qst; c[2] = qst >> 8; #else - emit_write_bytecode_byte_uint(emit, b, qst); + emit_write_bytecode_byte_uint(emit, stack_adj, b, qst); #endif } -STATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, mp_obj_t obj) { +STATIC void emit_write_bytecode_byte_obj(emit_t *emit, int stack_adj, byte b, mp_obj_t obj) { #if MICROPY_PERSISTENT_CODE - emit_write_bytecode_byte_const(emit, b, + emit_write_bytecode_byte_const(emit, stack_adj, b, emit->scope->num_pos_args + emit->scope->num_kwonly_args + emit->ct_cur_obj++, (mp_uint_t)obj); #else // aligns the pointer so it is friendly to GC - emit_write_bytecode_byte(emit, b); + emit_write_bytecode_byte(emit, stack_adj, b); emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(mp_obj_t)); mp_obj_t *c = (mp_obj_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_obj_t)); // Verify thar c is already uint-aligned @@ -262,14 +270,14 @@ STATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, mp_obj_t obj) { #endif } -STATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, byte b, mp_raw_code_t *rc) { +STATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, int stack_adj, byte b, mp_raw_code_t *rc) { #if MICROPY_PERSISTENT_CODE - emit_write_bytecode_byte_const(emit, b, + emit_write_bytecode_byte_const(emit, stack_adj, b, emit->scope->num_pos_args + emit->scope->num_kwonly_args + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)(uintptr_t)rc); #else // aligns the pointer so it is friendly to GC - emit_write_bytecode_byte(emit, b); + emit_write_bytecode_byte(emit, stack_adj, b); emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(void*)); void **c = (void**)emit_get_cur_to_write_bytecode(emit, sizeof(void*)); // Verify thar c is already uint-aligned @@ -279,7 +287,8 @@ STATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, byte b, mp_raw_code_ } // unsigned labels are relative to ip following this instruction, stored as 16 bits -STATIC void emit_write_bytecode_byte_unsigned_label(emit_t *emit, byte b1, mp_uint_t label) { +STATIC void emit_write_bytecode_byte_unsigned_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { + mp_emit_bc_adjust_stack_size(emit, stack_adj); mp_uint_t bytecode_offset; if (emit->pass < MP_PASS_EMIT) { bytecode_offset = 0; @@ -293,7 +302,8 @@ STATIC void emit_write_bytecode_byte_unsigned_label(emit_t *emit, byte b1, mp_ui } // signed labels are relative to ip following this instruction, stored as 16 bits, in excess -STATIC void emit_write_bytecode_byte_signed_label(emit_t *emit, byte b1, mp_uint_t label) { +STATIC void emit_write_bytecode_byte_signed_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { + mp_emit_bc_adjust_stack_size(emit, stack_adj); int bytecode_offset; if (emit->pass < MP_PASS_EMIT) { bytecode_offset = 0; @@ -364,10 +374,10 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { id_info_t *id = &scope->id_info[i]; if (id->kind == ID_INFO_KIND_CELL) { assert(id->local_num < 255); - emit_write_bytecode_byte(emit, id->local_num); // write the local which should be converted to a cell + emit_write_bytecode_raw_byte(emit, id->local_num); // write the local which should be converted to a cell } } - emit_write_bytecode_byte(emit, 255); // end of list sentinel + emit_write_bytecode_raw_byte(emit, 255); // end of list sentinel #if MICROPY_PERSISTENT_CODE emit->ct_cur_obj = 0; @@ -468,10 +478,6 @@ void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) { emit->last_emit_was_return_value = false; } -static inline void emit_bc_pre(emit_t *emit, mp_int_t stack_size_delta) { - mp_emit_bc_adjust_stack_size(emit, stack_size_delta); -} - void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { //printf("source: line %d -> %d offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->bytecode_offset); #if MICROPY_ENABLE_SOURCE_LINE @@ -493,7 +499,7 @@ void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { } void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { - emit_bc_pre(emit, 0); + mp_emit_bc_adjust_stack_size(emit, 0); if (emit->pass == MP_PASS_SCOPE) { return; } @@ -511,62 +517,52 @@ void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { void mp_emit_bc_import(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_IMPORT_NAME + MP_EMIT_IMPORT_NAME == MP_BC_IMPORT_NAME); MP_STATIC_ASSERT(MP_BC_IMPORT_NAME + MP_EMIT_IMPORT_FROM == MP_BC_IMPORT_FROM); - if (kind == MP_EMIT_IMPORT_FROM) { - emit_bc_pre(emit, 1); - } else { - emit_bc_pre(emit, -1); - } + int stack_adj = kind == MP_EMIT_IMPORT_FROM ? 1 : -1; if (kind == MP_EMIT_IMPORT_STAR) { - emit_write_bytecode_byte(emit, MP_BC_IMPORT_STAR); + emit_write_bytecode_byte(emit, stack_adj, MP_BC_IMPORT_STAR); } else { - emit_write_bytecode_byte_qstr(emit, MP_BC_IMPORT_NAME + kind, qst); + emit_write_bytecode_byte_qstr(emit, stack_adj, MP_BC_IMPORT_NAME + kind, qst); } } void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) { MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_NONE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_NONE); MP_STATIC_ASSERT(MP_BC_LOAD_CONST_FALSE + (MP_TOKEN_KW_TRUE - MP_TOKEN_KW_FALSE) == MP_BC_LOAD_CONST_TRUE); - emit_bc_pre(emit, 1); if (tok == MP_TOKEN_ELLIPSIS) { - emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); + emit_write_bytecode_byte_obj(emit, 1, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); } else { - emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_FALSE + (tok - MP_TOKEN_KW_FALSE)); + emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_CONST_FALSE + (tok - MP_TOKEN_KW_FALSE)); } } void mp_emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) { - emit_bc_pre(emit, 1); if (-16 <= arg && arg <= 47) { - emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_SMALL_INT_MULTI + 16 + arg); + emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_CONST_SMALL_INT_MULTI + 16 + arg); } else { - emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg); + emit_write_bytecode_byte_int(emit, 1, MP_BC_LOAD_CONST_SMALL_INT, arg); } } void mp_emit_bc_load_const_str(emit_t *emit, qstr qst) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qst); + emit_write_bytecode_byte_qstr(emit, 1, MP_BC_LOAD_CONST_STRING, qst); } void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, obj); + emit_write_bytecode_byte_obj(emit, 1, MP_BC_LOAD_CONST_OBJ, obj); } void mp_emit_bc_load_null(emit_t *emit) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL); + emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_NULL); } void mp_emit_bc_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_LOAD_FAST_N); MP_STATIC_ASSERT(MP_BC_LOAD_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_LOAD_DEREF); (void)qst; - emit_bc_pre(emit, 1); if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) { - emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num); + emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_FAST_MULTI + local_num); } else { - emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N + kind, local_num); + emit_write_bytecode_byte_uint(emit, 1, MP_BC_LOAD_FAST_N + kind, local_num); } } @@ -574,51 +570,45 @@ void mp_emit_bc_load_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_LOAD_NAME); MP_STATIC_ASSERT(MP_BC_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_LOAD_GLOBAL); (void)qst; - emit_bc_pre(emit, 1); - emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_NAME + kind, qst); + emit_write_bytecode_byte_qstr(emit, 1, MP_BC_LOAD_NAME + kind, qst); if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { - emit_write_bytecode_byte(emit, 0); + emit_write_bytecode_raw_byte(emit, 0); } } void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super) { - emit_bc_pre(emit, 1 - 2 * is_super); - emit_write_bytecode_byte_qstr(emit, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst); + int stack_adj = 1 - 2 * is_super; + emit_write_bytecode_byte_qstr(emit, stack_adj, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst); } void mp_emit_bc_load_build_class(emit_t *emit) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte(emit, MP_BC_LOAD_BUILD_CLASS); + emit_write_bytecode_byte(emit, 1, MP_BC_LOAD_BUILD_CLASS); } void mp_emit_bc_subscr(emit_t *emit, int kind) { if (kind == MP_EMIT_SUBSCR_LOAD) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte(emit, MP_BC_LOAD_SUBSCR); + emit_write_bytecode_byte(emit, -1, MP_BC_LOAD_SUBSCR); } else { if (kind == MP_EMIT_SUBSCR_DELETE) { mp_emit_bc_load_null(emit); mp_emit_bc_rot_three(emit); } - emit_bc_pre(emit, -3); - emit_write_bytecode_byte(emit, MP_BC_STORE_SUBSCR); + emit_write_bytecode_byte(emit, -3, MP_BC_STORE_SUBSCR); } } void mp_emit_bc_attr(emit_t *emit, qstr qst, int kind) { if (kind == MP_EMIT_ATTR_LOAD) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_ATTR, qst); + emit_write_bytecode_byte_qstr(emit, 0, MP_BC_LOAD_ATTR, qst); } else { if (kind == MP_EMIT_ATTR_DELETE) { mp_emit_bc_load_null(emit); mp_emit_bc_rot_two(emit); } - emit_bc_pre(emit, -2); - emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_ATTR, qst); + emit_write_bytecode_byte_qstr(emit, -2, MP_BC_STORE_ATTR, qst); } if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) { - emit_write_bytecode_byte(emit, 0); + emit_write_bytecode_raw_byte(emit, 0); } } @@ -626,98 +616,86 @@ void mp_emit_bc_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kin MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_STORE_FAST_N); MP_STATIC_ASSERT(MP_BC_STORE_FAST_N + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_STORE_DEREF); (void)qst; - emit_bc_pre(emit, -1); if (kind == MP_EMIT_IDOP_LOCAL_FAST && local_num <= 15) { - emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num); + emit_write_bytecode_byte(emit, -1, MP_BC_STORE_FAST_MULTI + local_num); } else { - emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N + kind, local_num); + emit_write_bytecode_byte_uint(emit, -1, MP_BC_STORE_FAST_N + kind, local_num); } } void mp_emit_bc_store_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_STORE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_STORE_NAME); MP_STATIC_ASSERT(MP_BC_STORE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_STORE_GLOBAL); - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_qstr(emit, MP_BC_STORE_NAME + kind, qst); + emit_write_bytecode_byte_qstr(emit, -1, MP_BC_STORE_NAME + kind, qst); } void mp_emit_bc_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_FAST == MP_BC_DELETE_FAST); MP_STATIC_ASSERT(MP_BC_DELETE_FAST + MP_EMIT_IDOP_LOCAL_DEREF == MP_BC_DELETE_DEREF); (void)qst; - emit_write_bytecode_byte_uint(emit, MP_BC_DELETE_FAST + kind, local_num); + emit_write_bytecode_byte_uint(emit, 0, MP_BC_DELETE_FAST + kind, local_num); } void mp_emit_bc_delete_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_BC_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_BC_DELETE_NAME); MP_STATIC_ASSERT(MP_BC_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_BC_DELETE_GLOBAL); - emit_bc_pre(emit, 0); - emit_write_bytecode_byte_qstr(emit, MP_BC_DELETE_NAME + kind, qst); + emit_write_bytecode_byte_qstr(emit, 0, MP_BC_DELETE_NAME + kind, qst); } void mp_emit_bc_dup_top(emit_t *emit) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte(emit, MP_BC_DUP_TOP); + emit_write_bytecode_byte(emit, 1, MP_BC_DUP_TOP); } void mp_emit_bc_dup_top_two(emit_t *emit) { - emit_bc_pre(emit, 2); - emit_write_bytecode_byte(emit, MP_BC_DUP_TOP_TWO); + emit_write_bytecode_byte(emit, 2, MP_BC_DUP_TOP_TWO); } void mp_emit_bc_pop_top(emit_t *emit) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte(emit, MP_BC_POP_TOP); + emit_write_bytecode_byte(emit, -1, MP_BC_POP_TOP); } void mp_emit_bc_rot_two(emit_t *emit) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte(emit, MP_BC_ROT_TWO); + emit_write_bytecode_byte(emit, 0, MP_BC_ROT_TWO); } void mp_emit_bc_rot_three(emit_t *emit) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte(emit, MP_BC_ROT_THREE); + emit_write_bytecode_byte(emit, 0, MP_BC_ROT_THREE); } void mp_emit_bc_jump(emit_t *emit, mp_uint_t label) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label); + emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_JUMP, label); } void mp_emit_bc_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { - emit_bc_pre(emit, -1); if (cond) { - emit_write_bytecode_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label); + emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_POP_JUMP_IF_TRUE, label); } else { - emit_write_bytecode_byte_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label); + emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_POP_JUMP_IF_FALSE, label); } } void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) { - emit_bc_pre(emit, -1); if (cond) { - emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label); + emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_JUMP_IF_TRUE_OR_POP, label); } else { - emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label); + emit_write_bytecode_byte_signed_label(emit, -1, MP_BC_JUMP_IF_FALSE_OR_POP, label); } } void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) { if (except_depth == 0) { - emit_bc_pre(emit, 0); if (label & MP_EMIT_BREAK_FROM_FOR) { // need to pop the iterator if we are breaking out of a for loop - emit_write_bytecode_byte(emit, MP_BC_POP_TOP); + emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP); // also pop the iter_buf for (size_t i = 0; i < MP_OBJ_ITER_BUF_NSLOTS - 1; ++i) { - emit_write_bytecode_byte(emit, MP_BC_POP_TOP); + emit_write_bytecode_raw_byte(emit, MP_BC_POP_TOP); } } - emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); + emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); } else { - emit_write_bytecode_byte_signed_label(emit, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); - emit_write_bytecode_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth); + emit_write_bytecode_byte_signed_label(emit, 0, MP_BC_UNWIND_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR); + emit_write_bytecode_raw_byte(emit, ((label & MP_EMIT_BREAK_FROM_FOR) ? 0x80 : 0) | except_depth); } } @@ -725,52 +703,45 @@ void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind) { MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_WITH == MP_BC_SETUP_WITH); MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_EXCEPT == MP_BC_SETUP_EXCEPT); MP_STATIC_ASSERT(MP_BC_SETUP_WITH + MP_EMIT_SETUP_BLOCK_FINALLY == MP_BC_SETUP_FINALLY); - if (kind == MP_EMIT_SETUP_BLOCK_WITH) { // The SETUP_WITH opcode pops ctx_mgr from the top of the stack // and then pushes 3 entries: __exit__, ctx_mgr, as_value. - emit_bc_pre(emit, 2); - } else { - emit_bc_pre(emit, 0); - } - emit_write_bytecode_byte_unsigned_label(emit, MP_BC_SETUP_WITH + kind, label); + int stack_adj = kind == MP_EMIT_SETUP_BLOCK_WITH ? 2 : 0; + emit_write_bytecode_byte_unsigned_label(emit, stack_adj, MP_BC_SETUP_WITH + kind, label); } void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) { mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE); mp_emit_bc_label_assign(emit, label); - emit_bc_pre(emit, 2); // ensure we have enough stack space to call the __exit__ method - emit_write_bytecode_byte(emit, MP_BC_WITH_CLEANUP); - emit_bc_pre(emit, -4); // cancel the 2 above, plus the 2 from mp_emit_bc_setup_block(MP_EMIT_SETUP_BLOCK_WITH) + // The +2 is to ensure we have enough stack space to call the __exit__ method + emit_write_bytecode_byte(emit, 2, MP_BC_WITH_CLEANUP); + // Cancel the +2 above, plus the +2 from mp_emit_bc_setup_block(MP_EMIT_SETUP_BLOCK_WITH) + mp_emit_bc_adjust_stack_size(emit, -4); } void mp_emit_bc_end_finally(emit_t *emit) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte(emit, MP_BC_END_FINALLY); + emit_write_bytecode_byte(emit, -1, MP_BC_END_FINALLY); } void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) { - emit_bc_pre(emit, use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0); - emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER); + int stack_adj = use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0; + emit_write_bytecode_byte(emit, stack_adj, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER); } void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte_unsigned_label(emit, MP_BC_FOR_ITER, label); + emit_write_bytecode_byte_unsigned_label(emit, 1, MP_BC_FOR_ITER, label); } void mp_emit_bc_for_iter_end(emit_t *emit) { - emit_bc_pre(emit, -MP_OBJ_ITER_BUF_NSLOTS); + mp_emit_bc_adjust_stack_size(emit, -MP_OBJ_ITER_BUF_NSLOTS); } void mp_emit_bc_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { (void)within_exc_handler; - emit_bc_pre(emit, 0); - emit_write_bytecode_byte_unsigned_label(emit, MP_BC_POP_EXCEPT_JUMP, label); + emit_write_bytecode_byte_unsigned_label(emit, 0, MP_BC_POP_EXCEPT_JUMP, label); } void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op); + emit_write_bytecode_byte(emit, 0, MP_BC_UNARY_OP_MULTI + op); } void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) { @@ -782,11 +753,9 @@ void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) { invert = true; op = MP_BINARY_OP_IS; } - emit_bc_pre(emit, -1); - emit_write_bytecode_byte(emit, MP_BC_BINARY_OP_MULTI + op); + emit_write_bytecode_byte(emit, -1, MP_BC_BINARY_OP_MULTI + op); if (invert) { - emit_bc_pre(emit, 0); - emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NOT); + emit_write_bytecode_byte(emit, 0, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NOT); } } @@ -796,17 +765,12 @@ void mp_emit_bc_build(emit_t *emit, mp_uint_t n_args, int kind) { MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_MAP == MP_BC_BUILD_MAP); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_SET == MP_BC_BUILD_SET); MP_STATIC_ASSERT(MP_BC_BUILD_TUPLE + MP_EMIT_BUILD_SLICE == MP_BC_BUILD_SLICE); - if (kind == MP_EMIT_BUILD_MAP) { - emit_bc_pre(emit, 1); - } else { - emit_bc_pre(emit, 1 - n_args); - } - emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_TUPLE + kind, n_args); + int stack_adj = kind == MP_EMIT_BUILD_MAP ? 1 : 1 - n_args; + emit_write_bytecode_byte_uint(emit, stack_adj, MP_BC_BUILD_TUPLE + kind, n_args); } void mp_emit_bc_store_map(emit_t *emit) { - emit_bc_pre(emit, -2); - emit_write_bytecode_byte(emit, MP_BC_STORE_MAP); + emit_write_bytecode_byte(emit, -2, MP_BC_STORE_MAP); } void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) { @@ -822,51 +786,46 @@ void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection n = 0; t = 2; } - emit_bc_pre(emit, -1 - n); // the lower 2 bits of the opcode argument indicate the collection type - emit_write_bytecode_byte_uint(emit, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t); + emit_write_bytecode_byte_uint(emit, -1 - n, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t); } void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) { - emit_bc_pre(emit, -1 + n_args); - emit_write_bytecode_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args); + emit_write_bytecode_byte_uint(emit, -1 + n_args, MP_BC_UNPACK_SEQUENCE, n_args); } void mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) { - emit_bc_pre(emit, -1 + n_left + n_right + 1); - emit_write_bytecode_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8)); + emit_write_bytecode_byte_uint(emit, -1 + n_left + n_right + 1, MP_BC_UNPACK_EX, n_left | (n_right << 8)); } void mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { - emit_bc_pre(emit, 1); - emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_FUNCTION, scope->raw_code); + emit_write_bytecode_byte_raw_code(emit, 1, MP_BC_MAKE_FUNCTION, scope->raw_code); } else { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code); + emit_write_bytecode_byte_raw_code(emit, -1, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code); } } void mp_emit_bc_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { - emit_bc_pre(emit, -n_closed_over + 1); - emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_CLOSURE, scope->raw_code); - emit_write_bytecode_byte(emit, n_closed_over); + int stack_adj = -n_closed_over + 1; + emit_write_bytecode_byte_raw_code(emit, stack_adj, MP_BC_MAKE_CLOSURE, scope->raw_code); + emit_write_bytecode_raw_byte(emit, n_closed_over); } else { assert(n_closed_over <= 255); - emit_bc_pre(emit, -2 - (mp_int_t)n_closed_over + 1); - emit_write_bytecode_byte_raw_code(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code); - emit_write_bytecode_byte(emit, n_closed_over); + int stack_adj = -2 - (mp_int_t)n_closed_over + 1; + emit_write_bytecode_byte_raw_code(emit, stack_adj, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code); + emit_write_bytecode_raw_byte(emit, n_closed_over); } } -STATIC void emit_bc_call_function_method_helper(emit_t *emit, mp_int_t stack_adj, mp_uint_t bytecode_base, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { +STATIC void emit_bc_call_function_method_helper(emit_t *emit, int stack_adj, mp_uint_t bytecode_base, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { if (star_flags) { - emit_bc_pre(emit, stack_adj - (mp_int_t)n_positional - 2 * (mp_int_t)n_keyword - 2); - emit_write_bytecode_byte_uint(emit, bytecode_base + 1, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? + stack_adj -= (int)n_positional + 2 * (int)n_keyword + 2; + emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base + 1, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? } else { - emit_bc_pre(emit, stack_adj - (mp_int_t)n_positional - 2 * (mp_int_t)n_keyword); - emit_write_bytecode_byte_uint(emit, bytecode_base, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? + stack_adj -= (int)n_positional + 2 * (int)n_keyword; + emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? } } @@ -879,22 +838,19 @@ void mp_emit_bc_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_ke } void mp_emit_bc_return_value(emit_t *emit) { - emit_bc_pre(emit, -1); + emit_write_bytecode_byte(emit, -1, MP_BC_RETURN_VALUE); emit->last_emit_was_return_value = true; - emit_write_bytecode_byte(emit, MP_BC_RETURN_VALUE); } void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) { assert(n_args <= 2); - emit_bc_pre(emit, -n_args); - emit_write_bytecode_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args); + emit_write_bytecode_byte_byte(emit, -n_args, MP_BC_RAISE_VARARGS, n_args); } void mp_emit_bc_yield(emit_t *emit, int kind) { MP_STATIC_ASSERT(MP_BC_YIELD_VALUE + 1 == MP_BC_YIELD_FROM); - emit_bc_pre(emit, -kind); + emit_write_bytecode_byte(emit, -kind, MP_BC_YIELD_VALUE + kind); emit->scope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; - emit_write_bytecode_byte(emit, MP_BC_YIELD_VALUE + kind); } void mp_emit_bc_start_except_handler(emit_t *emit) { From 2dfa69efbbae92faf21360edd5e60c5a9145a2dc Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 15:22:42 +1000 Subject: [PATCH 0360/1299] extmod/modujson: Support passing bytes/bytearray to json.loads. CPython allows this, and it can be useful to reduce the number of memory allocations. Fixes issue #5031. --- extmod/modujson.c | 8 ++++---- tests/extmod/ujson_loads.py | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/extmod/modujson.c b/extmod/modujson.c index f5c6428ef9c16..15ed2f38d828b 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2014-2016 Damien P. George + * Copyright (c) 2014-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -281,9 +281,9 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load); STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { - size_t len; - const char *buf = mp_obj_str_get_data(obj, &len); - vstr_t vstr = {len, len, (char*)buf, true}; + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ); + vstr_t vstr = {bufinfo.len, bufinfo.len, (char*)bufinfo.buf, true}; mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL}; return mod_ujson_load(MP_OBJ_FROM_PTR(&sio)); } diff --git a/tests/extmod/ujson_loads.py b/tests/extmod/ujson_loads.py index adba3c068d27c..43672d6505de4 100644 --- a/tests/extmod/ujson_loads.py +++ b/tests/extmod/ujson_loads.py @@ -37,6 +37,10 @@ def my_print(o): # whitespace handling my_print(json.loads('{\n\t"a":[]\r\n, "b":[1], "c":{"3":4} \n\r\t\r\r\r\n}')) +# loading from bytes and bytearray +my_print(json.loads(b'[1,2]')) +my_print(json.loads(bytearray(b'[null]'))) + # loading nothing should raise exception try: json.loads('') From 2eb88f5df74263cf4b458b135d16a100eb7a8bd2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 15:45:13 +1000 Subject: [PATCH 0361/1299] tests/extmod: Split json.loads of bytes/bytearray into separate test. Because this functionality was introduced in Python 3.6. --- tests/extmod/ujson_loads.py | 4 ---- tests/extmod/ujson_loads_bytes.py | 13 +++++++++++++ tests/extmod/ujson_loads_bytes.py.exp | 2 ++ 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 tests/extmod/ujson_loads_bytes.py create mode 100644 tests/extmod/ujson_loads_bytes.py.exp diff --git a/tests/extmod/ujson_loads.py b/tests/extmod/ujson_loads.py index 43672d6505de4..adba3c068d27c 100644 --- a/tests/extmod/ujson_loads.py +++ b/tests/extmod/ujson_loads.py @@ -37,10 +37,6 @@ def my_print(o): # whitespace handling my_print(json.loads('{\n\t"a":[]\r\n, "b":[1], "c":{"3":4} \n\r\t\r\r\r\n}')) -# loading from bytes and bytearray -my_print(json.loads(b'[1,2]')) -my_print(json.loads(bytearray(b'[null]'))) - # loading nothing should raise exception try: json.loads('') diff --git a/tests/extmod/ujson_loads_bytes.py b/tests/extmod/ujson_loads_bytes.py new file mode 100644 index 0000000000000..507e4ca885b7b --- /dev/null +++ b/tests/extmod/ujson_loads_bytes.py @@ -0,0 +1,13 @@ +# test loading from bytes and bytearray (introduced in Python 3.6) + +try: + import ujson as json +except ImportError: + try: + import json + except ImportError: + print("SKIP") + raise SystemExit + +print(json.loads(b'[1,2]')) +print(json.loads(bytearray(b'[null]'))) diff --git a/tests/extmod/ujson_loads_bytes.py.exp b/tests/extmod/ujson_loads_bytes.py.exp new file mode 100644 index 0000000000000..c2735a99052d2 --- /dev/null +++ b/tests/extmod/ujson_loads_bytes.py.exp @@ -0,0 +1,2 @@ +[1, 2] +[None] From bc9b656f35ff484a86f0b209881d8551814da800 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 15:59:14 +1000 Subject: [PATCH 0362/1299] py/runtime: Remove obsolete comment about mp_parse_compile_execute. mp_locals_get/set and mp_globals_get/set are now static-inline functions so this comment is no longer correct. --- py/runtime.c | 1 - 1 file changed, 1 deletion(-) diff --git a/py/runtime.c b/py/runtime.c index 04f9442b7b6a6..9e60eb6263ffe 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1421,7 +1421,6 @@ void mp_import_all(mp_obj_t module) { #if MICROPY_ENABLE_COMPILER -// this is implemented in this file so it can optimise access to locals/globals mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { // save context mp_obj_dict_t *volatile old_globals = mp_globals_get(); From 973c87d8fa41c3ae0c46be4f234726ecc3ac9d8a Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 16:05:05 +1000 Subject: [PATCH 0363/1299] py/objgenerator: Move defn of mp_const_GeneratorExit_obj here. Because the mp_obj_exception_t type is now globally available. --- py/objexcept.c | 5 ----- py/objgenerator.c | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/py/objexcept.c b/py/objexcept.c index 1fb636f666156..7e3fdcc27c9b5 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -100,11 +100,6 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { #endif #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF -// Instance of GeneratorExit exception - needed by generator.close() -// This would belong to objgenerator.c, but to keep mp_obj_exception_t -// definition module-private so far, have it here. -const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; - void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in); mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; diff --git a/py/objgenerator.c b/py/objgenerator.c index b7186b8d0bf0d..62e6446166863 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -34,6 +34,9 @@ #include "py/objfun.h" #include "py/stackctrl.h" +// Instance of GeneratorExit exception - needed by generator.close() +const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; + /******************************************************************************/ /* generator wrapper */ From 53527138a938a5119f7294480567526ade646ba6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 16:07:28 +1000 Subject: [PATCH 0364/1299] py/bc0.h: Add comment that MP_BC_MAKE_CLOSURE/_DEFARGS take extra byte. --- py/bc0.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/bc0.h b/py/bc0.h index 175ee263a00cb..fcb6eead5f03a 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -98,8 +98,8 @@ #define MP_BC_MAKE_FUNCTION (0x60) // uint #define MP_BC_MAKE_FUNCTION_DEFARGS (0x61) // uint -#define MP_BC_MAKE_CLOSURE (0x62) // uint -#define MP_BC_MAKE_CLOSURE_DEFARGS (0x63) // uint +#define MP_BC_MAKE_CLOSURE (0x62) // uint; byte +#define MP_BC_MAKE_CLOSURE_DEFARGS (0x63) // uint; byte #define MP_BC_CALL_FUNCTION (0x64) // uint #define MP_BC_CALL_FUNCTION_VAR_KW (0x65) // uint #define MP_BC_CALL_METHOD (0x66) // uint From 2fca0d7f18f8c31a6c85b598bb72f01725b26228 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 16:13:05 +1000 Subject: [PATCH 0365/1299] py/vm: Shorten error message for not-implemented opcode. It's really an opcode that's not implemented, so use "opcode" instead of "byte code". And remove the redundant "not implemented" text because that is already implied by the exception type. There's no need to have a long error message for an exception that is almost never encountered. Saves about 20 bytes of code size on most ports. --- py/vm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/py/vm.c b/py/vm.c index 260a7f38baf9d..6a4634d006586 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1262,7 +1262,8 @@ unwind_jump:; } else #endif { - mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented"); + + mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "opcode"); nlr_pop(); code_state->state[0] = obj; return MP_VM_RETURN_EXCEPTION; From 519746cae4b1dd6e2d006f294961494ee949a2cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 17:20:16 +1000 Subject: [PATCH 0366/1299] extmod/crypto-algorithms: Add source to header and populate copyright. As per the README.md of the upstream source at https://github.com/B-Con/crypto-algorithms, this source code was released into the public domain, so make that explicit in the copyright line in the header. --- extmod/crypto-algorithms/sha256.c | 3 ++- extmod/crypto-algorithms/sha256.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/extmod/crypto-algorithms/sha256.c b/extmod/crypto-algorithms/sha256.c index 276611cfd5032..24e964749b693 100644 --- a/extmod/crypto-algorithms/sha256.c +++ b/extmod/crypto-algorithms/sha256.c @@ -1,7 +1,8 @@ /********************************************************************* +* Source: https://github.com/B-Con/crypto-algorithms * Filename: sha256.c * Author: Brad Conte (brad AT bradconte.com) -* Copyright: +* Copyright: This code is released into the public domain. * Disclaimer: This code is presented "as is" without any guarantees. * Details: Implementation of the SHA-256 hashing algorithm. SHA-256 is one of the three algorithms in the SHA2 diff --git a/extmod/crypto-algorithms/sha256.h b/extmod/crypto-algorithms/sha256.h index caa1f81020184..9c19472ea292f 100644 --- a/extmod/crypto-algorithms/sha256.h +++ b/extmod/crypto-algorithms/sha256.h @@ -1,7 +1,8 @@ /********************************************************************* +* Source: https://github.com/B-Con/crypto-algorithms * Filename: sha256.h * Author: Brad Conte (brad AT bradconte.com) -* Copyright: +* Copyright: This code is released into the public domain. * Disclaimer: This code is presented "as is" without any guarantees. * Details: Defines the API for the corresponding SHA1 implementation. *********************************************************************/ From 3d7455a0bb4caa3e80e7594eaedd6e72c056ebe9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 27 Aug 2019 16:37:43 +1000 Subject: [PATCH 0367/1299] py/py.mk: Remove trailing spaces at end of line. --- py/py.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/py.mk b/py/py.mk index e649297e680c9..10beb29e45084 100644 --- a/py/py.mk +++ b/py/py.mk @@ -21,9 +21,9 @@ CSUPEROPT = -O3 # External modules written in C. ifneq ($(USER_C_MODULES),) -# pre-define USERMOD variables as expanded so that variables are immediate +# pre-define USERMOD variables as expanded so that variables are immediate # expanded as they're added to them -SRC_USERMOD := +SRC_USERMOD := CFLAGS_USERMOD := LDFLAGS_USERMOD := $(foreach module, $(wildcard $(USER_C_MODULES)/*/micropython.mk), \ From 16f6169c88a5fd93b151149e561d177557fcc760 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 21 Aug 2019 16:07:12 +1000 Subject: [PATCH 0368/1299] py/vm: Don't add traceback info for exc's propagated through a finally. With this patch exception tracebacks that go through a finally are improved (less confusing, match CPython), and it makes finally's slightly more efficient (in time and RAM) because they no longer need to add a traceback. Partially fixes issue #2928. --- py/vm.c | 9 +++++---- tests/misc/print_exception.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/py/vm.c b/py/vm.c index 6a4634d006586..64bddd6b5a59f 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1359,10 +1359,11 @@ unwind_jump:; #if MICROPY_STACKLESS unwind_loop: #endif - // set file and line number that the exception occurred at - // TODO: don't set traceback for exceptions re-raised by END_FINALLY. - // But consider how to handle nested exceptions. - if (nlr.ret_val != &mp_const_GeneratorExit_obj) { + // Set traceback info (file and line number) where the exception occurred, but not for: + // - constant GeneratorExit object, because it's const + // - exceptions re-raised by END_FINALLY + if (nlr.ret_val != &mp_const_GeneratorExit_obj + && *code_state->ip != MP_BC_END_FINALLY) { const byte *ip = code_state->fun_bc->bytecode; ip = mp_decode_uint_skip(ip); // skip n_state ip = mp_decode_uint_skip(ip); // skip n_exc_stack diff --git a/tests/misc/print_exception.py b/tests/misc/print_exception.py index 95431632f92ab..08b2e4bc48b3d 100644 --- a/tests/misc/print_exception.py +++ b/tests/misc/print_exception.py @@ -47,6 +47,16 @@ def g(): print('caught') print_exc(e) +# Test that an exception propagated through a finally doesn't have a traceback added there +try: + try: + f() + finally: + print('finally') +except Exception as e: + print('caught') + print_exc(e) + # Here we have a function with lots of bytecode generated for a single source-line, and # there is an error right at the end of the bytecode. It should report the correct line. def f(): From 08c1fe556915c912598d5a5d5db0f5942f3a333d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 21 Aug 2019 16:08:43 +1000 Subject: [PATCH 0369/1299] py/vm: Don't add traceback info for exceptions that are re-raised. With this patch exceptions that are re-raised have improved tracebacks (less confusing, match CPython), and it makes re-raise slightly more efficient (in time and RAM) because they no longer need to add a traceback. Also general VM performance is not measurably affected. Partially fixes issue #2928. --- py/vm.c | 4 +++- tests/misc/print_exception.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/py/vm.c b/py/vm.c index 64bddd6b5a59f..84296b463f44d 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1362,8 +1362,10 @@ unwind_jump:; // Set traceback info (file and line number) where the exception occurred, but not for: // - constant GeneratorExit object, because it's const // - exceptions re-raised by END_FINALLY + // - exceptions re-raised explicitly by "raise" if (nlr.ret_val != &mp_const_GeneratorExit_obj - && *code_state->ip != MP_BC_END_FINALLY) { + && *code_state->ip != MP_BC_END_FINALLY + && !(*code_state->ip == MP_BC_RAISE_VARARGS && code_state->ip[1] == 0)) { const byte *ip = code_state->fun_bc->bytecode; ip = mp_decode_uint_skip(ip); // skip n_state ip = mp_decode_uint_skip(ip); // skip n_exc_stack diff --git a/tests/misc/print_exception.py b/tests/misc/print_exception.py index 08b2e4bc48b3d..2067030bf9b5a 100644 --- a/tests/misc/print_exception.py +++ b/tests/misc/print_exception.py @@ -57,6 +57,18 @@ def g(): print('caught') print_exc(e) +# Test that re-raising an exception doesn't add traceback info +try: + try: + f() + except Exception as e: + print('reraise') + print_exc(e) + raise +except Exception as e: + print('caught') + print_exc(e) + # Here we have a function with lots of bytecode generated for a single source-line, and # there is an error right at the end of the bytecode. It should report the correct line. def f(): From b1e04848ef62d20db42b0b30f24304307c4e6765 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 21 Aug 2019 23:06:56 +1000 Subject: [PATCH 0370/1299] stm32/mphalport: Put PYBD specific MAC code in board specific file. --- ports/stm32/boards/PYBD_SF2/board_init.c | 26 +++++++++++++++++++++ ports/stm32/mphalport.c | 29 ++++++------------------ ports/stm32/mphalport.h | 1 + 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/ports/stm32/boards/PYBD_SF2/board_init.c b/ports/stm32/boards/PYBD_SF2/board_init.c index a8cf10f3a57d8..34f5e52a77136 100644 --- a/ports/stm32/boards/PYBD_SF2/board_init.c +++ b/ports/stm32/boards/PYBD_SF2/board_init.c @@ -24,9 +24,23 @@ * THE SOFTWARE. */ +#include #include "py/mphal.h" #include "storage.h" +#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) +#define OTP_ADDR (0x1ff079e0) +#else +#define OTP_ADDR (0x1ff0f3c0) +#endif +#define OTP ((pyb_otp_t*)OTP_ADDR) + +typedef struct _pyb_otp_t { + uint16_t series; + uint16_t rev; + uint8_t mac[6]; +} pyb_otp_t; + void mboot_board_early_init(void) { // Enable 500mA on WBUS-DIP28 mp_hal_pin_config(pyb_pin_W23, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); @@ -44,3 +58,15 @@ void board_sleep(int value) { mp_spiflash_deepsleep(&spi_bdev.spiflash, value); mp_spiflash_deepsleep(&spi_bdev2.spiflash, value); } + +void mp_hal_get_mac(int idx, uint8_t buf[6]) { + // Check if OTP region has a valid MAC address, and use it if it does + if (OTP->series == 0x00d1 && OTP->mac[0] == 'H' && OTP->mac[1] == 'J' && OTP->mac[2] == '0') { + memcpy(buf, OTP->mac, 6); + buf[5] += idx; + return; + } + + // Generate a random locally administered MAC address (LAA) + mp_hal_generate_laa_mac(idx, buf); +} diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index ec4590b06bb49..aa5dc33975030 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -168,28 +168,8 @@ void mp_hal_pin_config_speed(mp_hal_pin_obj_t pin_obj, uint32_t speed) { /*******************************************************************************/ // MAC address -typedef struct _pyb_otp_t { - uint16_t series; - uint16_t rev; - uint8_t mac[6]; -} pyb_otp_t; - -#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F732xx) || defined(STM32F733xx) -#define OTP_ADDR (0x1ff079e0) -#else -#define OTP_ADDR (0x1ff0f3c0) -#endif -#define OTP ((pyb_otp_t*)OTP_ADDR) - -MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { - // Check if OTP region has a valid MAC address, and use it if it does - if (OTP->series == 0x00d1 && OTP->mac[0] == 'H' && OTP->mac[1] == 'J' && OTP->mac[2] == '0') { - memcpy(buf, OTP->mac, 6); - buf[5] += idx; - return; - } - - // Generate a random locally administered MAC address (LAA) +// Generate a random locally administered MAC address (LAA) +void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) { uint8_t *id = (uint8_t *)MP_HAL_UNIQUE_ID_ADDRESS; buf[0] = 0x02; // LAA range buf[1] = (id[11] << 4) | (id[10] & 0xf); @@ -199,6 +179,11 @@ MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { buf[5] = (id[0] << 2) | idx; } +// A board can override this if needed +MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) { + mp_hal_generate_laa_mac(idx, buf); +} + void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) { static const char hexchr[16] = "0123456789ABCDEF"; uint8_t mac[6]; diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index bd71adf77bd4a..d73ff8bff36f7 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -82,5 +82,6 @@ enum { MP_HAL_MAC_ETH0, }; +void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]); void mp_hal_get_mac(int idx, uint8_t buf[6]); void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest); From 68d74b00743124ade07df0876bd93034d3542780 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 11:16:01 +1000 Subject: [PATCH 0371/1299] stm32/mboot/Makefile: Define "BUILDING_MBOOT" when building mboot. So boards can configure their settings based on whether mboot or the main firmware is being built. --- ports/stm32/mboot/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index f2c3baecc1a6b..19635b9183ed6 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -63,6 +63,7 @@ CFLAGS += -DSTM32_HAL_H='' CFLAGS += -DBOARD_$(BOARD) CFLAGS += -DAPPLICATION_ADDR=$(TEXT0_ADDR) CFLAGS += -DFFCONF_H=\"ports/stm32/mboot/ffconf.h\" +CFLAGS += -DBUILDING_MBOOT=1 LDFLAGS = -nostdlib -L . -T stm32_generic.ld -Map=$(@:.elf=.map) --cref LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) From 5789558d60fb6dcf0537a4487444e6f84a408561 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 22 Aug 2019 11:17:10 +1000 Subject: [PATCH 0372/1299] stm32/boards/PYBD_SF2: Exclude certain things when building mboot. --- ports/stm32/boards/PYBD_SF2/board_init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/board_init.c b/ports/stm32/boards/PYBD_SF2/board_init.c index 34f5e52a77136..d1a0a09e7a477 100644 --- a/ports/stm32/boards/PYBD_SF2/board_init.c +++ b/ports/stm32/boards/PYBD_SF2/board_init.c @@ -54,6 +54,8 @@ void board_early_init(void) { spi_bdev_ioctl(&spi_bdev2, BDEV_IOCTL_INIT, (uint32_t)&spiflash2_config); } +#if !BUILDING_MBOOT + void board_sleep(int value) { mp_spiflash_deepsleep(&spi_bdev.spiflash, value); mp_spiflash_deepsleep(&spi_bdev2.spiflash, value); @@ -70,3 +72,5 @@ void mp_hal_get_mac(int idx, uint8_t buf[6]) { // Generate a random locally administered MAC address (LAA) mp_hal_generate_laa_mac(idx, buf); } + +#endif From 15b36aa0af238b16d27a4d768d0d2dd462567665 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 23 Aug 2019 11:08:20 +1000 Subject: [PATCH 0373/1299] unix/main: Only accept full emit cmd-line options if native enabled. --- ports/unix/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index 004d581bb22ef..c8f0833503536 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -313,7 +313,11 @@ STATIC int usage(char **argv) { int impl_opts_cnt = 0; printf( " compile-only -- parse and compile only\n" +#if MICROPY_EMIT_NATIVE " emit={bytecode,native,viper} -- set the default code emitter\n" +#else +" emit=bytecode -- set the default code emitter\n" +#endif ); impl_opts_cnt++; #if MICROPY_ENABLE_GC @@ -343,10 +347,12 @@ STATIC void pre_process_options(int argc, char **argv) { compile_only = true; } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { emit_opt = MP_EMIT_OPT_BYTECODE; + #if MICROPY_EMIT_NATIVE } else if (strcmp(argv[a + 1], "emit=native") == 0) { emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; } else if (strcmp(argv[a + 1], "emit=viper") == 0) { emit_opt = MP_EMIT_OPT_VIPER; + #endif #if MICROPY_ENABLE_GC } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) { char *end; From 8e3e05761e1143a2502c7eca07c1b22bac192c84 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 23 Aug 2019 11:09:34 +1000 Subject: [PATCH 0374/1299] mpy-cross/main: Only accept full emit cmdline options if native enabled. --- mpy-cross/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 970ad2d75ff0c..6312a77469b6e 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -115,7 +115,11 @@ STATIC int usage(char **argv) { ); int impl_opts_cnt = 0; printf( +#if MICROPY_EMIT_NATIVE " emit={bytecode,native,viper} -- set the default code emitter\n" +#else +" emit=bytecode -- set the default code emitter\n" +#endif ); impl_opts_cnt++; printf( @@ -140,10 +144,12 @@ STATIC void pre_process_options(int argc, char **argv) { } if (strcmp(argv[a + 1], "emit=bytecode") == 0) { emit_opt = MP_EMIT_OPT_BYTECODE; + #if MICROPY_EMIT_NATIVE } else if (strcmp(argv[a + 1], "emit=native") == 0) { emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; } else if (strcmp(argv[a + 1], "emit=viper") == 0) { emit_opt = MP_EMIT_OPT_VIPER; + #endif } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) { char *end; heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0); From af20c2ead3e9bb397fdf89e316aa78b56f165013 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 23 Aug 2019 11:20:50 +1000 Subject: [PATCH 0375/1299] py: Add global default_emit_opt variable to make emit kind persistent. mp_compile no longer takes an emit_opt argument, rather this setting is now provided by the global default_emit_opt variable. Now, when -X emit=native is passed as a command-line option, the emitter will be set for all compiled modules (included imports), not just the top-level script. In the future there could be a way to also set this variable from a script. Fixes issue #4267. --- examples/embedding/hello-embed.c | 2 +- lib/upytesthelper/upytesthelper.c | 2 +- lib/utils/pyexec.c | 2 +- mpy-cross/main.c | 9 ++++++++- ports/bare-arm/main.c | 2 +- ports/javascript/main.c | 2 +- ports/minimal/main.c | 2 +- ports/nrf/main.c | 2 +- ports/qemu-arm/main.c | 2 +- ports/unix/main.c | 9 ++++++++- py/compile.c | 11 ++++++++--- py/compile.h | 4 ++-- py/mpstate.h | 3 +++ py/runtime.c | 5 ++++- 14 files changed, 41 insertions(+), 16 deletions(-) diff --git a/examples/embedding/hello-embed.c b/examples/embedding/hello-embed.c index 96596309660eb..2000b703c11c6 100644 --- a/examples/embedding/hello-embed.c +++ b/examples/embedding/hello-embed.c @@ -41,7 +41,7 @@ mp_obj_t execute_from_str(const char *str) { qstr src_name = 1/*MP_QSTR_*/; mp_lexer_t *lex = mp_lexer_new_from_str_len(src_name, str, strlen(str), false); mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_obj_t module_fun = mp_compile(&pt, src_name, MP_EMIT_OPT_NONE, false); + mp_obj_t module_fun = mp_compile(&pt, src_name, false); mp_call_function_0(module_fun); nlr_pop(); return 0; diff --git a/lib/upytesthelper/upytesthelper.c b/lib/upytesthelper/upytesthelper.c index d28c5b9cc0490..326172be658c0 100644 --- a/lib/upytesthelper/upytesthelper.c +++ b/lib/upytesthelper/upytesthelper.c @@ -101,7 +101,7 @@ void upytest_execute_test(const char *src) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index adb16937d0ad0..851b026b6fd35 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -89,7 +89,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input // source is a lexer, parse and compile the script qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL); + module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL); #else mp_raise_msg(&mp_type_RuntimeError, "script compilation not supported"); #endif diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 6312a77469b6e..afd24ca9f7334 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -72,7 +72,7 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha #endif mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_raw_code_t *rc = mp_compile_to_raw_code(&parse_tree, source_name, emit_opt, false); + mp_raw_code_t *rc = mp_compile_to_raw_code(&parse_tree, source_name, false); vstr_t vstr; vstr_init(&vstr, 16); @@ -196,6 +196,13 @@ MP_NOINLINE int main_(int argc, char **argv) { mp_obj_list_init(mp_sys_path, 0); mp_obj_list_init(mp_sys_argv, 0); + #if MICROPY_EMIT_NATIVE + // Set default emitter options + MP_STATE_VM(default_emit_opt) = emit_opt; + #else + (void)emit_opt; + #endif + // set default compiler configuration mp_dynamic_compiler.small_int_bits = 31; mp_dynamic_compiler.opt_cache_map_lookup_in_bytecode = 0; diff --git a/ports/bare-arm/main.c b/ports/bare-arm/main.c index b96fb47ace61a..4183944108d0e 100644 --- a/ports/bare-arm/main.c +++ b/ports/bare-arm/main.c @@ -13,7 +13,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/ports/javascript/main.c b/ports/javascript/main.c index f8ef0e7c559b9..77b8b873a5319 100644 --- a/ports/javascript/main.c +++ b/ports/javascript/main.c @@ -46,7 +46,7 @@ int do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/ports/minimal/main.c b/ports/minimal/main.c index 5e145dc8293d7..adc1dad0c6f95 100644 --- a/ports/minimal/main.c +++ b/ports/minimal/main.c @@ -16,7 +16,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/ports/nrf/main.c b/ports/nrf/main.c index e1ffce9385a20..29dd34f69dabf 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -81,7 +81,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) { if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; mp_parse_tree_t pn = mp_parse(lex, input_kind); - mp_obj_t module_fun = mp_compile(&pn, source_name, MP_EMIT_OPT_NONE, true); + mp_obj_t module_fun = mp_compile(&pn, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/ports/qemu-arm/main.c b/ports/qemu-arm/main.c index 4cdd1482879ed..41bf9457bac01 100644 --- a/ports/qemu-arm/main.c +++ b/ports/qemu-arm/main.c @@ -18,7 +18,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/ports/unix/main.c b/ports/unix/main.c index c8f0833503536..65a4dd8a10adb 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -138,7 +138,7 @@ STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu } #endif - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, emit_opt, is_repl); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, is_repl); if (!compile_only) { // execute it @@ -456,6 +456,13 @@ MP_NOINLINE int main_(int argc, char **argv) { mp_init(); + #if MICROPY_EMIT_NATIVE + // Set default emitter options + MP_STATE_VM(default_emit_opt) = emit_opt; + #else + (void)emit_opt; + #endif + #if MICROPY_VFS_POSIX { // Mount the host FS at the root of our internal VFS diff --git a/py/compile.c b/py/compile.c index c0ae3de1145ac..829472c0d724b 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3437,7 +3437,7 @@ STATIC void scope_compute_things(scope_t *scope) { #if !MICROPY_PERSISTENT_CODE_SAVE STATIC #endif -mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) { +mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) { // put compiler state on the stack, it's relatively small compiler_t comp_state = {0}; compiler_t *comp = &comp_state; @@ -3448,6 +3448,11 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f comp->continue_label = INVALID_LABEL; // create the module scope + #if MICROPY_EMIT_NATIVE + const uint emit_opt = MP_STATE_VM(default_emit_opt); + #else + const uint emit_opt = MP_EMIT_OPT_NONE; + #endif scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, parse_tree->root, emit_opt); // create standard emitter; it's used at least for MP_PASS_SCOPE @@ -3602,8 +3607,8 @@ mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_f } } -mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) { - mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, emit_opt, is_repl); +mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) { + mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, is_repl); // return function that executes the outer module return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL); } diff --git a/py/compile.h b/py/compile.h index 99a17a8d1ed35..1ad1f5e9cd3fc 100644 --- a/py/compile.h +++ b/py/compile.h @@ -32,11 +32,11 @@ // the compiler will raise an exception if an error occurred // the compiler will clear the parse tree before it returns -mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl); +mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl); #if MICROPY_PERSISTENT_CODE_SAVE // this has the same semantics as mp_compile -mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl); +mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl); #endif // this is implemented in runtime.c diff --git a/py/mpstate.h b/py/mpstate.h index 1057cef04185d..83fea3eb41d81 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -205,6 +205,9 @@ typedef struct _mp_state_vm_t { #if MICROPY_ENABLE_COMPILER mp_uint_t mp_optimise_value; + #if MICROPY_EMIT_NATIVE + uint8_t default_emit_opt; // one of MP_EMIT_OPT_xxx + #endif #endif // size of the emergency exception buf, if it's dynamically allocated diff --git a/py/runtime.c b/py/runtime.c index 9e60eb6263ffe..d81321e86282e 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -88,6 +88,9 @@ void mp_init(void) { #if MICROPY_ENABLE_COMPILER // optimization disabled by default MP_STATE_VM(mp_optimise_value) = 0; + #if MICROPY_EMIT_NATIVE + MP_STATE_VM(default_emit_opt) = MP_EMIT_OPT_NONE; + #endif #endif // init global module dict @@ -1434,7 +1437,7 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, parse_input_kind); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); mp_obj_t ret; if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) { From b3152b2de7115f5b2ca7a1b5240a33c0fb24bdc0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 23 Aug 2019 11:25:46 +1000 Subject: [PATCH 0376/1299] tests: Split out test for optimisation level and line-no printing. --- tests/micropython/opt_level.py | 5 ----- tests/micropython/opt_level.py.exp | 3 --- tests/micropython/opt_level_lineno.py | 6 ++++++ tests/micropython/opt_level_lineno.py.exp | 3 +++ tests/run-tests | 1 + 5 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 tests/micropython/opt_level_lineno.py create mode 100644 tests/micropython/opt_level_lineno.py.exp diff --git a/tests/micropython/opt_level.py b/tests/micropython/opt_level.py index 5a10047f04d4f..4e2f2f4ea3249 100644 --- a/tests/micropython/opt_level.py +++ b/tests/micropython/opt_level.py @@ -12,8 +12,3 @@ micropython.opt_level(1) exec('print(__debug__)') exec('assert 0') - -# check that level 3 doesn't store line numbers -# the expected output is that any line is printed as "line 1" -micropython.opt_level(3) -exec('try:\n xyz\nexcept NameError as er:\n import sys\n sys.print_exception(er)') diff --git a/tests/micropython/opt_level.py.exp b/tests/micropython/opt_level.py.exp index 6372f6c5d6056..74b3dd74e8260 100644 --- a/tests/micropython/opt_level.py.exp +++ b/tests/micropython/opt_level.py.exp @@ -2,6 +2,3 @@ 1 True False -Traceback (most recent call last): - File "", line 1, in -NameError: name 'xyz' isn't defined diff --git a/tests/micropython/opt_level_lineno.py b/tests/micropython/opt_level_lineno.py new file mode 100644 index 0000000000000..00e5739605754 --- /dev/null +++ b/tests/micropython/opt_level_lineno.py @@ -0,0 +1,6 @@ +import micropython as micropython + +# check that level 3 doesn't store line numbers +# the expected output is that any line is printed as "line 1" +micropython.opt_level(3) +exec('try:\n xyz\nexcept NameError as er:\n import sys\n sys.print_exception(er)') diff --git a/tests/micropython/opt_level_lineno.py.exp b/tests/micropython/opt_level_lineno.py.exp new file mode 100644 index 0000000000000..469b90ba7938a --- /dev/null +++ b/tests/micropython/opt_level_lineno.py.exp @@ -0,0 +1,3 @@ +Traceback (most recent call last): + File "", line 1, in +NameError: name 'xyz' isn't defined diff --git a/tests/run-tests b/tests/run-tests index c45d2787e2f98..b22d067192911 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -377,6 +377,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_tests.add('misc/sys_exc_info.py') # sys.exc_info() is not supported for native skip_tests.add('micropython/emg_exc.py') # because native doesn't have proper traceback info skip_tests.add('micropython/heapalloc_traceback.py') # because native doesn't have proper traceback info + skip_tests.add('micropython/opt_level_lineno.py') # native doesn't have proper traceback info skip_tests.add('micropython/schedule.py') # native code doesn't check pending events for test_file in tests: From 0bec07f32b04a8249e1c732acb7eeb56ac125398 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 23 Aug 2019 19:49:10 +0200 Subject: [PATCH 0377/1299] stm32/extint: Fix EXTI mapping of PVD and RTC events for H7 MCUs. --- ports/stm32/extint.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index 836b0c5954de6..c5b3b0c6a7e77 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -163,7 +163,12 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, - #if defined(STM32WB) + #if defined(STM32H7) + PVD_AVD_IRQn, + RTC_Alarm_IRQn, + TAMP_STAMP_IRQn, + RTC_WKUP_IRQn, + #elif defined(STM32WB) PVD_PVM_IRQn, RTC_Alarm_IRQn, TAMP_STAMP_LSECSS_IRQn, From afc8596c154f86b8d612a7ac28b999e8ea26df55 Mon Sep 17 00:00:00 2001 From: "Paul m. p. P" Date: Tue, 27 Aug 2019 01:20:43 +0200 Subject: [PATCH 0378/1299] docs/reference/speed_python: Add missing self to var caching example. --- docs/reference/speed_python.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst index f2d7739fb0a50..aa0b54cb50ed7 100644 --- a/docs/reference/speed_python.rst +++ b/docs/reference/speed_python.rst @@ -165,7 +165,7 @@ by caching the object in a local variable: class foo(object): def __init__(self): - ba = bytearray(100) + self.ba = bytearray(100) def bar(self, obj_display): ba_ref = self.ba fb = obj_display.framebuffer From 5635b96461e7806c06fccfa237dae670cc2a1377 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 27 Aug 2019 10:11:03 -0700 Subject: [PATCH 0379/1299] esp32: Add 'config' function to network.LAN, reusing network.WLAN. --- ports/esp32/modnetwork.c | 48 +++++++++++++++++++++++++++------------ ports/esp32/modnetwork.h | 1 + ports/esp32/network_lan.c | 1 + 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 3dfe3945bb9d9..45ea5139c68f0 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -550,17 +550,24 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); - // get the config for the interface + bool is_wifi = self->if_id == WIFI_IF_AP || self->if_id == WIFI_IF_STA; + wifi_config_t cfg; - ESP_EXCEPTIONS(esp_wifi_get_config(self->if_id, &cfg)); + if (is_wifi) { + ESP_EXCEPTIONS(esp_wifi_get_config(self->if_id, &cfg)); + } + + #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) if (kwargs->used != 0) { + if (!is_wifi) { + goto unknown; + } for (size_t i = 0; i < kwargs->alloc; i++) { if (mp_map_slot_is_filled(kwargs, i)) { int req_if = -1; - #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) switch ((uintptr_t)kwargs->table[i].key) { case QS(MP_QSTR_mac): { mp_buffer_info_t bufinfo; @@ -612,7 +619,6 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs default: goto unknown; } - #undef QS // We post-check interface requirements to save on code size if (req_if >= 0) { @@ -633,20 +639,34 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs } int req_if = -1; - mp_obj_t val; + mp_obj_t val = mp_const_none; - #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) switch ((uintptr_t)args[1]) { case QS(MP_QSTR_mac): { uint8_t mac[6]; - ESP_EXCEPTIONS(esp_wifi_get_mac(self->if_id, mac)); - return mp_obj_new_bytes(mac, sizeof(mac)); + switch (self->if_id) { + case WIFI_IF_AP: // fallthrough intentional + case WIFI_IF_STA: + ESP_EXCEPTIONS(esp_wifi_get_mac(self->if_id, mac)); + return mp_obj_new_bytes(mac, sizeof(mac)); + + case ESP_IF_ETH: + esp_eth_get_mac(mac); + return mp_obj_new_bytes(mac, sizeof(mac)); + default: + goto unknown; + } } case QS(MP_QSTR_essid): - if (self->if_id == WIFI_IF_STA) { - val = mp_obj_new_str((char*)cfg.sta.ssid, strlen((char*)cfg.sta.ssid)); - } else { - val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len); + switch (self->if_id) { + case WIFI_IF_STA: + val = mp_obj_new_str((char*)cfg.sta.ssid, strlen((char*)cfg.sta.ssid)); + break; + case WIFI_IF_AP: + val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len); + break; + default: + req_if = WIFI_IF_AP; } break; case QS(MP_QSTR_hidden): @@ -670,6 +690,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs default: goto unknown; } + #undef QS // We post-check interface requirements to save on code size @@ -682,8 +703,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs unknown: mp_raise_ValueError("unknown config param"); } - -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config); +MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config); STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&esp_active_obj) }, diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h index f39a2919d7d57..64d2da018c056 100644 --- a/ports/esp32/modnetwork.h +++ b/ports/esp32/modnetwork.h @@ -31,6 +31,7 @@ enum { PHY_LAN8720, PHY_TLK110 }; MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj); MP_DECLARE_CONST_FUN_OBJ_1(ppp_make_new_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(esp_config_obj); void usocket_events_deinit(void); diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 10f17ebcf81b1..100894b2eeb14 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -205,6 +205,7 @@ STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&lan_active_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&lan_isconnected_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) }, { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) }, }; From 1fe1ff935b258a79f42796bbdc8bb858f5bff462 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 28 Aug 2019 13:34:45 +1000 Subject: [PATCH 0380/1299] nrf: Clean up source by removing tabs, trailing spaces, non-ASCII chars. --- ports/nrf/boards/common.ld | 8 ++--- .../boards/microbit/modules/microbitdisplay.c | 20 ++++++------- .../boards/microbit/modules/microbitimage.c | 18 ++++++------ .../boards/microbit/modules/microbitimage.h | 6 ++-- ports/nrf/device/startup_nrf51822.c | 4 +-- ports/nrf/drivers/bluetooth/ble_drv.c | 2 +- ports/nrf/drivers/bluetooth/ble_uart.c | 4 +-- ports/nrf/drivers/ticker.h | 2 +- ports/nrf/fatfs_port.c | 2 +- ports/nrf/main.c | 29 +++++++++---------- ports/nrf/modules/ble/help_sd.h | 2 +- ports/nrf/modules/machine/pin.c | 12 ++++---- ports/nrf/modules/machine/pwm.c | 2 +- ports/nrf/modules/machine/spi.c | 10 +++---- ports/nrf/modules/machine/temp.c | 4 +-- ports/nrf/modules/random/modrandom.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_delegate.c | 2 +- .../nrf/modules/ubluepy/ubluepy_peripheral.c | 2 +- ports/nrf/modules/ubluepy/ubluepy_service.c | 2 +- ports/nrf/mphalport.h | 2 +- ports/nrf/pin_defs_nrf5.h | 6 ++-- 21 files changed, 70 insertions(+), 71 deletions(-) diff --git a/ports/nrf/boards/common.ld b/ports/nrf/boards/common.ld index 2e1e6f7358cf0..6edd33cf0178a 100644 --- a/ports/nrf/boards/common.ld +++ b/ports/nrf/boards/common.ld @@ -16,7 +16,7 @@ SECTIONS . = ALIGN(4); _etext = .; /* define a global symbol at end of code */ } >FLASH_TEXT - + /* .ARM.extab : { @@ -30,10 +30,10 @@ SECTIONS __exidx_end = .; } >FLASH */ - + /* used by the startup to initialize data */ _sidata = LOADADDR(.data); - + /* This is the initialized data section The program executes knowing that the data is in the RAM but the loader puts the initial values in the FLASH (inidata). @@ -49,7 +49,7 @@ SECTIONS . = ALIGN(4); _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ } >RAM AT>FLASH_TEXT - + /* Uninitialized data section */ .bss : { diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c index 936a3ec977568..2d70817503c45 100644 --- a/ports/nrf/boards/microbit/modules/microbitdisplay.c +++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c @@ -256,15 +256,15 @@ static const uint16_t render_timings[] = // The scale is (approximately) exponential, // each step is approx x1.9 greater than the previous. { 0, // Bright, Ticks Duration, Relative power - 2, // 1, 2, 32µs, inf - 2, // 2, 4, 64µs, 200% - 4, // 3, 8, 128µs, 200% - 7, // 4, 15, 240µs, 187% - 13, // 5, 28, 448µs, 187% - 25, // 6, 53, 848µs, 189% - 49, // 7, 102, 1632µs, 192% - 97, // 8, 199, 3184µs, 195% -// Always on 9, 375, 6000µs, 188% + 2, // 1, 2, 32us, inf + 2, // 2, 4, 64us, 200% + 4, // 3, 8, 128us, 200% + 7, // 4, 15, 240us, 187% + 13, // 5, 28, 448us, 187% + 25, // 6, 53, 848us, 189% + 49, // 7, 102, 1632us, 192% + 97, // 8, 199, 3184us, 195% +// Always on 9, 375, 6000us, 188% }; #define DISPLAY_TICKER_SLOT 1 @@ -281,7 +281,7 @@ static int32_t callback(void) { return -1; } display->previous_brightness = brightness; - // Return interval (in 16µs ticks) until next callback + // Return interval (in 16us ticks) until next callback return render_timings[brightness]; } diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index 9cba30f8782ec..fca5075089f98 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -62,7 +62,7 @@ STATIC void microbit_image_print(const mp_print_t *print, mp_obj_t self_in, mp_p uint8_t monochromeGetPixelValue(monochrome_5by5_t * p_mono, mp_int_t x, mp_int_t y) { unsigned int index = y*5+x; - if (index == 24) + if (index == 24) return p_mono->pixel44; return (p_mono->bits24[index>>3] >> (index&7))&1; } @@ -380,7 +380,7 @@ mp_obj_t microbit_image_set_pixel(mp_uint_t n_args, const mp_obj_t *args) { mp_raise_ValueError("index cannot be negative"); } mp_int_t bright = mp_obj_get_int(args[3]); - if (bright < 0 || bright > MAX_BRIGHTNESS) + if (bright < 0 || bright > MAX_BRIGHTNESS) mp_raise_ValueError("brightness out of bounds."); if (x < imageWidth(self) && y < imageHeight(self)) { greyscaleSetPixelValue(&(self->greyscale), x, y, bright); @@ -610,7 +610,7 @@ microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_float_t f #else microbit_image_obj_t *microbit_image_dim(microbit_image_obj_t *lhs, mp_int_t fval) { #endif - if (fval < 0) + if (fval < 0) mp_raise_ValueError("Brightness multiplier must not be negative."); greyscale_t *result = greyscale_new(imageWidth(lhs), imageHeight(lhs)); for (int x = 0; x < imageWidth(lhs); ++x) { @@ -639,7 +639,7 @@ microbit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_ima int val; int lval = imageGetPixelValue(lhs, x,y); int rval = imageGetPixelValue(rhs, x,y); - if (add) + if (add) val = min(lval + rval, MAX_BRIGHTNESS); else val = max(0, lval - rval); @@ -647,7 +647,7 @@ microbit_image_obj_t *microbit_image_sum(microbit_image_obj_t *lhs, microbit_ima } } return (microbit_image_obj_t *)result; -} +} STATIC mp_obj_t image_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (mp_obj_get_type(lhs_in) != µbit_image_type) { @@ -697,9 +697,9 @@ const mp_obj_type_t microbit_image_type = { .buffer_p = {NULL}, .locals_dict = (mp_obj_dict_t*)µbit_image_locals_dict, }; - + typedef struct _scrolling_string_t { - mp_obj_base_t base; + mp_obj_base_t base; char const *str; mp_uint_t len; mp_obj_t ref; @@ -708,7 +708,7 @@ typedef struct _scrolling_string_t { } scrolling_string_t; typedef struct _scrolling_string_iterator_t { - mp_obj_base_t base; + mp_obj_base_t base; mp_obj_t ref; greyscale_t *img; char const *next_char; @@ -962,7 +962,7 @@ const mp_obj_type_t microbit_facade_iterator_type = { }; mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) { - (void)iter_buf; + (void)iter_buf; facade_iterator_t *result = m_new_obj(facade_iterator_t); string_image_facade_t *iterable = (string_image_facade_t *)iterable_in; result->base.type = µbit_facade_iterator_type; diff --git a/ports/nrf/boards/microbit/modules/microbitimage.h b/ports/nrf/boards/microbit/modules/microbitimage.h index 23edbd6baac2d..41a6aff4ccd14 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.h +++ b/ports/nrf/boards/microbit/modules/microbitimage.h @@ -2,15 +2,15 @@ #define __MICROPY_INCLUDED_MICROBIT_IMAGE_H__ #include "py/runtime.h" - + #define MAX_BRIGHTNESS 9 -/** Monochrome images are immutable, which means that +/** Monochrome images are immutable, which means that * we only need one bit per pixel which saves quite a lot * of memory */ /* we reserve a couple of bits, so we won't need to modify the - * layout if we need to add more functionality or subtypes. */ + * layout if we need to add more functionality or subtypes. */ #define TYPE_AND_FLAGS \ mp_obj_base_t base; \ uint8_t five:1; \ diff --git a/ports/nrf/device/startup_nrf51822.c b/ports/nrf/device/startup_nrf51822.c index 2f15f0f49c7f8..2063e272743e5 100644 --- a/ports/nrf/device/startup_nrf51822.c +++ b/ports/nrf/device/startup_nrf51822.c @@ -48,8 +48,8 @@ void Reset_Handler(void) { // RAM on in on-mode *ram_on_addr = 3; // block 0 and 1 *ram_on_b_addr = 3; // block 2 and 3 -#if 0 - // RAM on in off-mode +#if 0 + // RAM on in off-mode ram_on_addr = 1 << 16; ram_on_b_addr = 1 << 17; #endif diff --git a/ports/nrf/drivers/bluetooth/ble_drv.c b/ports/nrf/drivers/bluetooth/ble_drv.c index ff3c885c153f5..e01d118487c77 100644 --- a/ports/nrf/drivers/bluetooth/ble_drv.c +++ b/ports/nrf/drivers/bluetooth/ble_drv.c @@ -418,7 +418,7 @@ bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { p_adv_params->p_device_name, p_adv_params->device_name_len) != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - "Can not apply device name in the stack.")); + "Can not apply device name in the stack.")); } BLE_DRIVER_LOG("Device name applied\n"); diff --git a/ports/nrf/drivers/bluetooth/ble_uart.c b/ports/nrf/drivers/bluetooth/ble_uart.c index 4a23cd6d2cc2c..b94780e26011b 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.c +++ b/ports/nrf/drivers/bluetooth/ble_uart.c @@ -190,7 +190,7 @@ void ble_uart_init0(void) { ble_uart_char_tx.service_handle = ble_uart_service.handle; bool retval = ble_drv_characteristic_add(&ble_uart_char_tx); if (retval) { - ble_uart_char_tx.p_service = &ble_uart_service; + ble_uart_char_tx.p_service = &ble_uart_service; } mp_obj_list_append(ble_uart_service.char_list, MP_OBJ_FROM_PTR(&ble_uart_char_tx)); @@ -198,7 +198,7 @@ void ble_uart_init0(void) { ble_uart_char_rx.service_handle = ble_uart_service.handle; retval = ble_drv_characteristic_add(&ble_uart_char_rx); if (retval) { - ble_uart_char_rx.p_service = &ble_uart_service; + ble_uart_char_rx.p_service = &ble_uart_service; } mp_obj_list_append(ble_uart_service.char_list, MP_OBJ_FROM_PTR(&ble_uart_char_rx)); diff --git a/ports/nrf/drivers/ticker.h b/ports/nrf/drivers/ticker.h index f6a95a9a25751..86f1c244778b0 100644 --- a/ports/nrf/drivers/ticker.h +++ b/ports/nrf/drivers/ticker.h @@ -35,7 +35,7 @@ #define __MICROPY_INCLUDED_LIB_TICKER_H__ /************************************* - * 62.5kHz (16µs cycle time) ticker. + * 62.5kHz (16us cycle time) ticker. ************************************/ #include "nrf.h" diff --git a/ports/nrf/fatfs_port.c b/ports/nrf/fatfs_port.c index 13ac21fb1bcca..6a17f627bd585 100644 --- a/ports/nrf/fatfs_port.c +++ b/ports/nrf/fatfs_port.c @@ -28,6 +28,6 @@ #include "lib/oofatfs/ff.h" DWORD get_fattime(void) { - // TODO: Implement this function. For now, fake it. + // TODO: Implement this function. For now, fake it. return ((2016 - 1980) << 25) | ((12) << 21) | ((4) << 16) | ((00) << 11) | ((18) << 5) | (23 / 2); } diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 29dd34f69dabf..38d41bd8c523a 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -94,7 +94,7 @@ extern uint32_t _heap_start; extern uint32_t _heap_end; int main(int argc, char **argv) { - + soft_reset: mp_stack_set_top(&_ram_end); @@ -185,8 +185,8 @@ pin_init0(); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib)); - // use SD card as current directory - f_chdrive("/sd"); + // use SD card as current directory + f_chdrive("/sd"); } no_mem_for_sd:; } @@ -293,18 +293,17 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); void HardFault_Handler(void) { #if defined(NRF52_SERIES) - static volatile uint32_t reg; - static volatile uint32_t reg2; - static volatile uint32_t bfar; - reg = SCB->HFSR; - reg2 = SCB->CFSR; - bfar = SCB->BFAR; - for (int i = 0; i < 0; i++) - { - (void)reg; - (void)reg2; - (void)bfar; - } + static volatile uint32_t reg; + static volatile uint32_t reg2; + static volatile uint32_t bfar; + reg = SCB->HFSR; + reg2 = SCB->CFSR; + bfar = SCB->BFAR; + for (int i = 0; i < 0; i++) { + (void)reg; + (void)reg2; + (void)bfar; + } #endif } diff --git a/ports/nrf/modules/ble/help_sd.h b/ports/nrf/modules/ble/help_sd.h index 027bbdd513489..69ee5a53811d1 100644 --- a/ports/nrf/modules/ble/help_sd.h +++ b/ports/nrf/modules/ble/help_sd.h @@ -39,7 +39,7 @@ " ble.enabled() -- check whether bluetooth stack is enabled\n" \ " ble.address() -- return device address as text string\n" \ "\n" - + #else #define HELP_TEXT_SD #endif // MICROPY_PY_BLE diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index d56abfd04e953..4e5b3434f96d6 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -127,12 +127,12 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) { const pin_obj_t *pin_obj; // If pin is SMALL_INT if (mp_obj_is_small_int(user_obj)) { - uint8_t value = MP_OBJ_SMALL_INT_VALUE(user_obj); + uint8_t value = MP_OBJ_SMALL_INT_VALUE(user_obj); for (uint8_t i = 0; i < machine_pin_num_of_pins; i++) { if (machine_pin_obj[i].pin == value) { return &machine_pin_obj[i]; - } - } + } + } } // If a pin was provided, then use it @@ -364,8 +364,8 @@ STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, con nrf_gpio_pin_dir_t mode = (nrf_gpio_pin_dir_t)args[0].u_int; // Connect input or not - nrf_gpio_pin_input_t input = (mode == NRF_GPIO_PIN_DIR_INPUT) ? NRF_GPIO_PIN_INPUT_CONNECT - : NRF_GPIO_PIN_INPUT_DISCONNECT; + nrf_gpio_pin_input_t input = (mode == NRF_GPIO_PIN_DIR_INPUT) ? NRF_GPIO_PIN_INPUT_CONNECT + : NRF_GPIO_PIN_INPUT_DISCONNECT; if (mode == NRF_GPIO_PIN_DIR_OUTPUT || mode == NRF_GPIO_PIN_DIR_INPUT) { nrf_gpio_cfg(self->pin, @@ -496,7 +496,7 @@ STATIC void pin_common_irq_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t } STATIC mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum {ARG_handler, ARG_trigger, ARG_wake}; + enum {ARG_handler, ARG_trigger, ARG_wake}; static const mp_arg_t allowed_args[] = { { MP_QSTR_handler, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = mp_const_none} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = NRF_GPIOTE_POLARITY_LOTOHI | NRF_GPIOTE_POLARITY_HITOLO} }, diff --git a/ports/nrf/modules/machine/pwm.c b/ports/nrf/modules/machine/pwm.c index cf8749302b4ae..195d47e6b1904 100644 --- a/ports/nrf/modules/machine/pwm.c +++ b/ports/nrf/modules/machine/pwm.c @@ -269,7 +269,7 @@ STATIC mp_obj_t machine_hard_pwm_make_new(mp_arg_val_t *args) { } else { self->p_config->mode = MODE_HIGH_LOW; } - + return MP_OBJ_FROM_PTR(self); } diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c index 1c401b76d2920..4361a8f8f9d70 100644 --- a/ports/nrf/modules/machine/spi.c +++ b/ports/nrf/modules/machine/spi.c @@ -154,9 +154,9 @@ STATIC int spi_find(mp_obj_t id) { void spi_transfer(const machine_hard_spi_obj_t * self, size_t len, const void * src, void * dest) { nrfx_spi_xfer_desc_t xfer_desc = { .p_tx_buffer = src, - .tx_length = len, - .p_rx_buffer = dest, - .rx_length = len + .tx_length = len, + .p_rx_buffer = dest, + .rx_length = len }; nrfx_spi_xfer(self->p_spi, &xfer_desc, 0); @@ -340,7 +340,7 @@ STATIC void machine_hard_spi_init(mp_obj_t self_in, mp_arg_val_t *args) { // Active high if (args[ARG_INIT_polarity].u_int == 0) { - if (args[ARG_INIT_phase].u_int == 0) { + if (args[ARG_INIT_phase].u_int == 0) { // First clock edge self->p_config->mode = NRF_SPI_MODE_0; } else { @@ -349,7 +349,7 @@ STATIC void machine_hard_spi_init(mp_obj_t self_in, mp_arg_val_t *args) { } // Active low } else { - if (args[ARG_INIT_phase].u_int == 0) { + if (args[ARG_INIT_phase].u_int == 0) { // First clock edge self->p_config->mode = NRF_SPI_MODE_2; } else { diff --git a/ports/nrf/modules/machine/temp.c b/ports/nrf/modules/machine/temp.c index 361d988857890..007a7e5fd8e95 100644 --- a/ports/nrf/modules/machine/temp.c +++ b/ports/nrf/modules/machine/temp.c @@ -67,9 +67,9 @@ STATIC mp_obj_t machine_temp_make_new(const mp_obj_type_t *type, size_t n_args, // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - + machine_temp_obj_t *self = m_new_obj(machine_temp_obj_t); - + self->base.type = &machine_temp_type; return MP_OBJ_FROM_PTR(self); diff --git a/ports/nrf/modules/random/modrandom.c b/ports/nrf/modules/random/modrandom.c index f67bffb27786a..a1395bce611e5 100644 --- a/ports/nrf/modules/random/modrandom.c +++ b/ports/nrf/modules/random/modrandom.c @@ -72,7 +72,7 @@ uint32_t machine_rng_generate_random_word(void) { status = sd_rand_application_vector_get((uint8_t *)&retval, 4); // Extract 4 bytes } while (status != 0); - return retval; + return retval; } #endif diff --git a/ports/nrf/modules/ubluepy/ubluepy_delegate.c b/ports/nrf/modules/ubluepy/ubluepy_delegate.c index 07bb7f49286fd..74ad52bbfa35b 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_delegate.c +++ b/ports/nrf/modules/ubluepy/ubluepy_delegate.c @@ -72,7 +72,7 @@ STATIC const mp_rom_map_elem_t ubluepy_delegate_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_handleConnection), MP_ROM_PTR(&ubluepy_delegate_handle_conn_obj) }, { MP_ROM_QSTR(MP_QSTR_handleNotification), MP_ROM_PTR(&ubluepy_delegate_handle_notif_obj) }, #if 0 - { MP_ROM_QSTR(MP_QSTR_handleDiscovery), MP_ROM_PTR(&ubluepy_delegate_handle_disc_obj) }, + { MP_ROM_QSTR(MP_QSTR_handleDiscovery), MP_ROM_PTR(&ubluepy_delegate_handle_disc_obj) }, #endif }; diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c index 3a45e56a07648..8f07daa2a3297 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c +++ b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c @@ -481,7 +481,7 @@ STATIC const mp_rom_map_elem_t ubluepy_peripheral_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_advertise), MP_ROM_PTR(&ubluepy_peripheral_advertise_obj) }, #endif #if MICROPY_PY_UBLUEPY_OBSERVER - // Nothing yet. + // Nothing yet. #endif }; diff --git a/ports/nrf/modules/ubluepy/ubluepy_service.c b/ports/nrf/modules/ubluepy/ubluepy_service.c index e5bf42a09fd30..a38136611fff7 100644 --- a/ports/nrf/modules/ubluepy/ubluepy_service.c +++ b/ports/nrf/modules/ubluepy/ubluepy_service.c @@ -162,7 +162,7 @@ STATIC const mp_rom_map_elem_t ubluepy_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_addCharacteristic), MP_ROM_PTR(&ubluepy_service_add_char_obj) }, { MP_ROM_QSTR(MP_QSTR_getCharacteristics), MP_ROM_PTR(&ubluepy_service_get_chars_obj) }, #if 0 - // Properties + // Properties { MP_ROM_QSTR(MP_QSTR_peripheral), MP_ROM_PTR(&ubluepy_service_get_peripheral_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&ubluepy_service_get_uuid_obj) }, diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index 18ff454fe6dc9..b374da403c8f7 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -42,7 +42,7 @@ typedef enum } HAL_StatusTypeDef; static inline uint32_t hal_tick_fake(void) { - return 0; + return 0; } #define mp_hal_ticks_ms hal_tick_fake // TODO: implement. Right now, return 0 always diff --git a/ports/nrf/pin_defs_nrf5.h b/ports/nrf/pin_defs_nrf5.h index c84d048a424e2..99020ded7531f 100644 --- a/ports/nrf/pin_defs_nrf5.h +++ b/ports/nrf/pin_defs_nrf5.h @@ -53,9 +53,9 @@ enum { }; #define PIN_DEFS_PORT_AF_UNION \ - NRF_UART_Type *UART; -// NRF_SPI_Type *SPIM; -// NRF_SPIS_Type *SPIS; + NRF_UART_Type *UART; +// NRF_SPI_Type *SPIM; +// NRF_SPIS_Type *SPIS; typedef NRF_GPIO_Type pin_gpio_t; From 400a128e11b94cc268685d1b7b26c613a34ca8c3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 29 Aug 2019 12:00:18 +1000 Subject: [PATCH 0381/1299] stm32/stm32_it: Include correct EXTI interrupt handlers for L0 MCUs. --- ports/stm32/stm32_it.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index a2ebb6641a45e..9f5a886f3d827 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -531,7 +531,7 @@ void RTC_WKUP_IRQHandler(void) { IRQ_EXIT(RTC_WKUP_IRQn); } -#if defined(STM32F0) +#if defined(STM32F0) || defined(STM32L0) void RTC_IRQHandler(void) { IRQ_ENTER(RTC_IRQn); From c7c6703950ef14f04ff9ad9d6b61b4b0666144c0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 28 Aug 2019 11:37:43 +1000 Subject: [PATCH 0382/1299] py/compile: Improve the line numbering precision for lambdas. Prior to this patch the line number for a lambda would be "line 1" if the body of the lambda contained only a simple expression (with no line number stored in the parse node). Now the line number is always reported correctly. --- py/compile.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/py/compile.c b/py/compile.c index 829472c0d724b..41ff66a8ca0ad 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3078,6 +3078,9 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3); + // Set the source line number for the start of the lambda + EMIT_ARG(set_source_line, pns->source_line); + // work out number of parameters, keywords and default parameters, and add them to the id_info array // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) if (comp->pass == MP_PASS_SCOPE) { From dbf35d3da359a2ddbccb1ea2116da37e23ce46bf Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 30 Aug 2019 16:41:08 +1000 Subject: [PATCH 0383/1299] py/bc: Factor out code to get bytecode line number info into new func. --- py/bc.h | 27 +++++++++++++++++++++++++++ py/vm.c | 24 +----------------------- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/py/bc.h b/py/bc.h index 0aadfa8a30578..bedffa795ee7b 100644 --- a/py/bc.h +++ b/py/bc.h @@ -119,4 +119,31 @@ uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint); #endif +static inline size_t mp_bytecode_get_source_line(const byte *line_info, size_t bc_offset) { + size_t source_line = 1; + size_t c; + while ((c = *line_info)) { + size_t b, l; + if ((c & 0x80) == 0) { + // 0b0LLBBBBB encoding + b = c & 0x1f; + l = c >> 5; + line_info += 1; + } else { + // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) + b = c & 0xf; + l = ((c << 4) & 0x700) | line_info[1]; + line_info += 2; + } + if (bc_offset >= b) { + bc_offset -= b; + source_line += l; + } else { + // found source line corresponding to bytecode offset + break; + } + } + return source_line; +} + #endif // MICROPY_INCLUDED_PY_BC_H diff --git a/py/vm.c b/py/vm.c index 84296b463f44d..0bc20346139b0 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1387,29 +1387,7 @@ unwind_jump:; qstr source_file = mp_decode_uint_value(ip); ip = mp_decode_uint_skip(ip); #endif - size_t source_line = 1; - size_t c; - while ((c = *ip)) { - size_t b, l; - if ((c & 0x80) == 0) { - // 0b0LLBBBBB encoding - b = c & 0x1f; - l = c >> 5; - ip += 1; - } else { - // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) - b = c & 0xf; - l = ((c << 4) & 0x700) | ip[1]; - ip += 2; - } - if (bc >= b) { - bc -= b; - source_line += l; - } else { - // found source line corresponding to bytecode offset - break; - } - } + size_t source_line = mp_bytecode_get_source_line(ip, bc); mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name); } From c96aedad4691d864c073890a7a20abc7ebd2de27 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Wed, 14 Aug 2019 15:59:38 +0200 Subject: [PATCH 0384/1299] py/profile: Add initial implementation of sys.settrace feature. --- py/profile.c | 441 +++++++++++++++++++++++++++++++++++++++++++++++++++ py/profile.h | 69 ++++++++ 2 files changed, 510 insertions(+) create mode 100644 py/profile.c create mode 100644 py/profile.h diff --git a/py/profile.c b/py/profile.c new file mode 100644 index 0000000000000..39578f6dcd5fd --- /dev/null +++ b/py/profile.c @@ -0,0 +1,441 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) SatoshiLabs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/profile.h" +#include "py/bc0.h" +#include "py/gc.h" + +#if MICROPY_PY_SYS_SETTRACE + +#define prof_trace_cb MP_STATE_THREAD(prof_trace_callback) + +STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) { + const mp_bytecode_prelude_t *prelude = &rc->prelude; + return mp_bytecode_get_source_line(prelude->line_info, bc + prelude->opcodes - prelude->locals); +} + +void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) { + const byte *ip = bytecode; + + prelude->n_state = mp_decode_uint(&ip); + prelude->n_exc_stack = mp_decode_uint(&ip); + prelude->scope_flags = *ip++; + prelude->n_pos_args = *ip++; + prelude->n_kwonly_args = *ip++; + prelude->n_def_pos_args = *ip++; + + const byte *code_info = ip; + size_t code_info_size = mp_decode_uint(&ip); + + qstr block_name = ip[0] | (ip[1] << 8); + qstr source_file = ip[2] | (ip[3] << 8); + ip += 4; + prelude->qstr_block_name = block_name; + prelude->qstr_source_file = source_file; + + prelude->line_info = ip; + prelude->locals = code_info + code_info_size; + + ip = prelude->locals; + while (*ip++ != 255) { + } + prelude->opcodes = ip; +} + +/******************************************************************************/ +// code object + +STATIC void code_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { + (void)kind; + mp_obj_code_t *o = MP_OBJ_TO_PTR(o_in); + const mp_raw_code_t *rc = o->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + mp_printf(print, + "", + prelude->qstr_block_name, + o, + prelude->qstr_source_file, + rc->line_of_definition + ); +} + +STATIC mp_obj_tuple_t* code_consts(const mp_raw_code_t *rc) { + const mp_bytecode_prelude_t *prelude = &rc->prelude; + int start = prelude->n_pos_args + prelude->n_kwonly_args + rc->n_obj; + int stop = prelude->n_pos_args + prelude->n_kwonly_args + rc->n_obj + rc->n_raw_code; + mp_obj_tuple_t *consts = MP_OBJ_TO_PTR(mp_obj_new_tuple(stop - start + 1, NULL)); + + size_t const_no = 0; + for (int i = start; i < stop; ++i) { + mp_obj_t code = mp_obj_new_code((const mp_raw_code_t*)MP_OBJ_TO_PTR(rc->const_table[i])); + if (code == MP_OBJ_NULL) { + m_malloc_fail(sizeof(mp_obj_code_t)); + } + consts->items[const_no++] = code; + } + consts->items[const_no++] = mp_const_none; + + return consts; +} + +STATIC mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) { + // const mp_bytecode_prelude_t *prelude = &rc->prelude; + uint start = 0; + uint stop = rc->fun_data_len - start; + + uint last_lineno = mp_prof_bytecode_lineno(rc, start); + uint lasti = 0; + + const uint buffer_chunk_size = (stop-start) >> 2; // heuristic magic + uint buffer_size = buffer_chunk_size; + byte *buffer = m_new(byte, buffer_size); + uint buffer_index = 0; + + for (uint i = start; i < stop; ++i) { + uint lineno = mp_prof_bytecode_lineno(rc, i); + size_t line_diff = lineno - last_lineno; + if (line_diff > 0) { + uint instr_diff = (i - start) - lasti; + + assert(instr_diff < 256); + assert(line_diff < 256); + + if (buffer_index + 2 > buffer_size) { + buffer = m_renew(byte, buffer, buffer_size, buffer_size + buffer_chunk_size); + buffer_size = buffer_size + buffer_chunk_size; + } + last_lineno = lineno; + lasti = i - start; + buffer[buffer_index++] = instr_diff; + buffer[buffer_index++] = line_diff; + } + } + + mp_obj_t o = mp_obj_new_bytes(buffer, buffer_index); + m_del(byte, buffer, buffer_size); + return o; +} + +STATIC void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if (dest[0] != MP_OBJ_NULL) { + // not load attribute + return; + } + mp_obj_code_t *o = MP_OBJ_TO_PTR(self_in); + const mp_raw_code_t *rc = o->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + switch(attr) { + case MP_QSTR_co_code: + dest[0] = mp_obj_new_bytes( + (void*)prelude->opcodes, + rc->fun_data_len - (prelude->opcodes - (const byte*)rc->fun_data) + ); + break; + case MP_QSTR_co_consts: + dest[0] = MP_OBJ_FROM_PTR(code_consts(rc)); + break; + case MP_QSTR_co_filename: + dest[0] = MP_OBJ_NEW_QSTR(prelude->qstr_source_file); + break; + case MP_QSTR_co_firstlineno: + dest[0] = MP_OBJ_NEW_SMALL_INT(mp_prof_bytecode_lineno(rc, 0)); + break; + case MP_QSTR_co_name: + dest[0] = MP_OBJ_NEW_QSTR(prelude->qstr_block_name); + break; + case MP_QSTR_co_names: + dest[0] = MP_OBJ_FROM_PTR(o->dict_locals); + break; + case MP_QSTR_co_lnotab: + if (!o->lnotab) { + o->lnotab = raw_code_lnotab(rc); + } + dest[0] = o->lnotab; + break; + } +} + +const mp_obj_type_t mp_type_code = { + { &mp_type_type }, + .name = MP_QSTR_code, + .print = code_print, + .unary_op = mp_generic_unary_op, + .attr = code_attr, +}; + +mp_obj_t mp_obj_new_code(const mp_raw_code_t *rc) { + mp_obj_code_t *o = m_new_obj_maybe(mp_obj_code_t); + if (o == NULL) { + return MP_OBJ_NULL; + } + o->base.type = &mp_type_code; + o->rc = rc; + o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly? + o->lnotab = MP_OBJ_NULL; + return MP_OBJ_FROM_PTR(o); +} + +/******************************************************************************/ +// frame object + +STATIC void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { + (void)kind; + mp_obj_frame_t *frame = MP_OBJ_TO_PTR(o_in); + mp_obj_code_t *code = frame->code; + const mp_raw_code_t *rc = code->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + mp_printf(print, + "", + frame, + prelude->qstr_source_file, + frame->lineno, + prelude->qstr_block_name + ); +} + +STATIC void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if (dest[0] != MP_OBJ_NULL) { + // not load attribute + return; + } + + mp_obj_frame_t *o = MP_OBJ_TO_PTR(self_in); + + switch(attr) { + case MP_QSTR_f_back: + dest[0] = mp_const_none; + if (o->code_state->prev_state) { + dest[0] = MP_OBJ_FROM_PTR(o->code_state->prev_state->frame); + } + break; + case MP_QSTR_f_code: + dest[0] = MP_OBJ_FROM_PTR(o->code); + break; + case MP_QSTR_f_globals: + dest[0] = MP_OBJ_FROM_PTR(o->code_state->fun_bc->globals); + break; + case MP_QSTR_f_lasti: + dest[0] = MP_OBJ_NEW_SMALL_INT(o->lasti); + break; + case MP_QSTR_f_lineno: + dest[0] = MP_OBJ_NEW_SMALL_INT(o->lineno); + break; + } +} + +const mp_obj_type_t mp_type_frame = { + { &mp_type_type }, + .name = MP_QSTR_frame, + .print = frame_print, + .unary_op = mp_generic_unary_op, + .attr = frame_attr, +}; + +mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) { + if (gc_is_locked()) { + return MP_OBJ_NULL; + } + + mp_obj_frame_t *o = m_new_obj_maybe(mp_obj_frame_t); + if (o == NULL) { + return MP_OBJ_NULL; + } + + mp_obj_code_t *code = o->code = MP_OBJ_TO_PTR(mp_obj_new_code(code_state->fun_bc->rc)); + if (code == NULL) { + return MP_OBJ_NULL; + } + + const mp_raw_code_t *rc = code->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + o->code_state = code_state; + o->base.type = &mp_type_frame; + o->back = NULL; + o->code = code; + o->lasti = code_state->ip - prelude->opcodes; + o->lineno = mp_prof_bytecode_lineno(rc, o->lasti); + o->trace_opcodes = false; + o->callback = MP_OBJ_NULL; + + return MP_OBJ_FROM_PTR(o); +} + + +/******************************************************************************/ +// Trace logic + +typedef struct { + struct _mp_obj_frame_t * frame; + mp_obj_t event; + mp_obj_t arg; +} prof_callback_args_t; + +STATIC mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t *args) { + assert(mp_obj_is_callable(callback)); + + mp_prof_is_executing = true; + + mp_obj_t a[3] = {MP_OBJ_FROM_PTR(args->frame), args->event, args->arg}; + mp_obj_t top = mp_call_function_n_kw(callback, 3, 0, a); + + mp_prof_is_executing = false; + + if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { + mp_obj_t obj = MP_STATE_VM(mp_pending_exception); + MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; + nlr_raise(obj); + } + return top; +} + +mp_obj_t mp_prof_settrace(mp_obj_t callback) { + if (mp_obj_is_callable(callback)) { + prof_trace_cb = callback; + } else { + prof_trace_cb = MP_OBJ_NULL; + } + return mp_const_none; +} + +mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state) { + assert(!mp_prof_is_executing); + + mp_obj_frame_t *frame = MP_OBJ_TO_PTR(mp_obj_new_frame(code_state)); + if (frame == NULL) { + // Couldn't allocate a frame object + return MP_OBJ_NULL; + } + + if (code_state->prev_state && code_state->frame == NULL) { + // We are entering not-yet-traced frame + // which means it's a CALL event (not a GENERATOR) + // so set the function definition line. + const mp_raw_code_t *rc = code_state->fun_bc->rc; + frame->lineno = rc->line_of_definition; + if (!rc->line_of_definition) { + frame->lineno = mp_prof_bytecode_lineno(rc, 0); + } + } + code_state->frame = frame; + + if (!prof_trace_cb) { + return MP_OBJ_NULL; + } + + mp_obj_t top; + prof_callback_args_t _args, *args=&_args; + args->frame = code_state->frame; + + // SETTRACE event CALL + args->event = MP_OBJ_NEW_QSTR(MP_QSTR_call); + args->arg = mp_const_none; + top = mp_prof_callback_invoke(prof_trace_cb, args); + + code_state->frame->callback = mp_obj_is_callable(top) ? top : MP_OBJ_NULL; + + // Invalidate the last executed line number so the LINE trace can trigger after this CALL. + frame->lineno = 0; + + return top; +} + +mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state) { + mp_obj_frame_t *frame = code_state->frame; + if (frame == NULL) { + // Frame was not allocated (eg because there was no memory available) + return MP_OBJ_NULL; + } + + mp_obj_frame_t *o = frame; + mp_obj_code_t *code = o->code; + const mp_raw_code_t *rc = code->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + + assert(o->code_state == code_state); + + o->lasti = code_state->ip - prelude->opcodes; + o->lineno = mp_prof_bytecode_lineno(rc, o->lasti); + + return MP_OBJ_FROM_PTR(o); +} + +mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception) { + // Detect execution recursion + assert(!mp_prof_is_executing); + assert(code_state->frame); + assert(mp_obj_get_type(code_state->frame) == &mp_type_frame); + + // Detect data recursion + assert(code_state != code_state->prev_state); + + mp_obj_t top = mp_const_none; + mp_obj_t callback = code_state->frame->callback; + + prof_callback_args_t _args, *args=&_args; + args->frame = code_state->frame; + args->event = mp_const_none; + args->arg = mp_const_none; + + // Call event's are handled inside mp_prof_frame_enter + + // SETTRACE event EXCEPTION + if (is_exception) { + args->event = MP_OBJ_NEW_QSTR(MP_QSTR_exception); + top = mp_prof_callback_invoke(callback, args); + return top; + } + + // SETTRACE event LINE + const mp_raw_code_t *rc = code_state->fun_bc->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + size_t prev_line_no = args->frame->lineno; + size_t current_line_no = mp_prof_bytecode_lineno(rc, code_state->ip - prelude->opcodes); + if (prev_line_no != current_line_no) { + args->frame->lineno = current_line_no; + args->event = MP_OBJ_NEW_QSTR(MP_QSTR_line); + top = mp_prof_callback_invoke(callback, args); + } + + // SETTRACE event RETURN + const byte *ip = code_state->ip; + if (*ip == MP_BC_RETURN_VALUE || *ip == MP_BC_YIELD_VALUE) { + args->event = MP_OBJ_NEW_QSTR(MP_QSTR_return); + top = mp_prof_callback_invoke(callback, args); + if (code_state->prev_state && *ip == MP_BC_RETURN_VALUE) { + code_state->frame->callback = MP_OBJ_NULL; + } + } + + // SETTRACE event OPCODE + // TODO: frame.f_trace_opcodes=True + if (false) { + args->event = MP_OBJ_NEW_QSTR(MP_QSTR_opcode); + } + + return top; +} + +#endif // MICROPY_PY_SYS_SETTRACE diff --git a/py/profile.h b/py/profile.h new file mode 100644 index 0000000000000..227634b564cc2 --- /dev/null +++ b/py/profile.h @@ -0,0 +1,69 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) SatoshiLabs + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_PY_PROFILING_H +#define MICROPY_INCLUDED_PY_PROFILING_H + +#include "py/emitglue.h" + +#if MICROPY_PY_SYS_SETTRACE + +#define mp_prof_is_executing MP_STATE_THREAD(prof_callback_is_executing) + +typedef struct _mp_obj_code_t { + mp_obj_base_t base; + const mp_raw_code_t *rc; + mp_obj_dict_t *dict_locals; + mp_obj_t lnotab; +} mp_obj_code_t; + +typedef struct _mp_obj_frame_t { + mp_obj_base_t base; + const mp_code_state_t *code_state; + struct _mp_obj_frame_t *back; + mp_obj_t callback; + mp_obj_code_t *code; + mp_uint_t lasti; + mp_uint_t lineno; + bool trace_opcodes; +} mp_obj_frame_t; + +void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude); + +mp_obj_t mp_obj_new_code(const mp_raw_code_t *rc); +mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state); + +// This is the implementation for the sys.settrace +mp_obj_t mp_prof_settrace(mp_obj_t callback); + +mp_obj_t mp_prof_frame_enter(mp_code_state_t *code_state); +mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state); + +// For every VM instruction tick this function deduces events from the state +mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception); + +#endif // MICROPY_PY_SYS_SETTRACE +#endif // MICROPY_INCLUDED_PY_PROFILING_H From 310b3d1b81d561e19d719acd89ee47b759e3795c Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Wed, 14 Aug 2019 16:09:36 +0200 Subject: [PATCH 0385/1299] py: Integrate sys.settrace feature into the VM and runtime. This commit adds support for sys.settrace, allowing to install Python handlers to trace execution of Python code. The interface follows CPython as closely as possible. The feature is disabled by default and can be enabled via MICROPY_PY_SYS_SETTRACE. --- ports/unix/main.c | 5 +++ ports/unix/mpconfigport.h | 4 ++ py/bc.c | 5 +++ py/bc.h | 18 ++++++++ py/compile.c | 6 +++ py/emitbc.c | 3 ++ py/emitglue.c | 15 +++++++ py/emitglue.h | 9 ++++ py/modsys.c | 17 ++++++++ py/mpconfig.h | 15 +++++++ py/mpstate.h | 6 +++ py/objfun.h | 3 ++ py/py.mk | 1 + py/runtime.c | 6 +++ py/vm.c | 89 ++++++++++++++++++++++++++++++++++++++- 15 files changed, 201 insertions(+), 1 deletion(-) diff --git a/ports/unix/main.c b/ports/unix/main.c index 65a4dd8a10adb..9147feb32d9c3 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -655,7 +655,12 @@ MP_NOINLINE int main_(int argc, char **argv) { } } + #if MICROPY_PY_SYS_SETTRACE + MP_STATE_THREAD(prof_trace_callback) = MP_OBJ_NULL; + #endif + #if MICROPY_PY_SYS_ATEXIT + // Beware, the sys.settrace callback should be disabled before running sys.atexit. if (mp_obj_is_callable(MP_STATE_VM(sys_exitfunc))) { mp_call_function_0(MP_STATE_VM(sys_exitfunc)); } diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 23c562e5aa3f2..0ff6b2b06d927 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -91,6 +91,10 @@ #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_ATEXIT (1) +#if MICROPY_PY_SYS_SETTRACE +#define MICROPY_PERSISTENT_CODE_SAVE (1) +#define MICROPY_COMP_CONST (0) +#endif #if defined(__APPLE__) && defined(__MACH__) #define MICROPY_PY_SYS_PLATFORM "darwin" #else diff --git a/py/bc.c b/py/bc.c index b178e7c202f71..7d0b13bd748fe 100644 --- a/py/bc.c +++ b/py/bc.c @@ -119,6 +119,11 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw code_state->prev = NULL; #endif + #if MICROPY_PY_SYS_SETTRACE + code_state->prev_state = NULL; + code_state->frame = NULL; + #endif + // get params size_t n_state = mp_decode_uint(&code_state->ip); code_state->ip = mp_decode_uint_skip(code_state->ip); // skip n_exc_stack diff --git a/py/bc.h b/py/bc.h index bedffa795ee7b..ac9105a553147 100644 --- a/py/bc.h +++ b/py/bc.h @@ -60,6 +60,20 @@ // const0 : obj // constN : obj +typedef struct _mp_bytecode_prelude_t { + uint n_state; + uint n_exc_stack; + uint scope_flags; + uint n_pos_args; + uint n_kwonly_args; + uint n_def_pos_args; + qstr qstr_block_name; + qstr qstr_source_file; + const byte *line_info; + const byte *locals; + const byte *opcodes; +} mp_bytecode_prelude_t; + // Exception stack entry typedef struct _mp_exc_stack_t { const byte *handler; @@ -84,6 +98,10 @@ typedef struct _mp_code_state_t { #if MICROPY_STACKLESS struct _mp_code_state_t *prev; #endif + #if MICROPY_PY_SYS_SETTRACE + struct _mp_code_state_t *prev_state; + struct _mp_obj_frame_t *frame; + #endif // Variable-length mp_obj_t state[0]; // Variable-length, never accessed by name, only as (void*)(state + n_state) diff --git a/py/compile.c b/py/compile.c index 41ff66a8ca0ad..8b2d820b3b657 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1608,6 +1608,9 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ qstr qstr_exception_local = 0; uint end_finally_label = comp_next_label(comp); + #if MICROPY_PY_SYS_SETTRACE + EMIT_ARG(set_source_line, pns_except->source_line); + #endif if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) { // this is a catch all exception handler @@ -3157,6 +3160,9 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { scope_find_or_add_id(scope, MP_QSTR___class__, ID_INFO_KIND_LOCAL); } + #if MICROPY_PY_SYS_SETTRACE + EMIT_ARG(set_source_line, pns->source_line); + #endif compile_load_id(comp, MP_QSTR___name__); compile_store_id(comp, MP_QSTR___module__); EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name diff --git a/py/emitbc.c b/py/emitbc.c index fcbd979d27542..ef0d20a10201e 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -284,6 +284,9 @@ STATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, int stack_adj, byte assert(c == MP_ALIGN(c, sizeof(void*))); *c = rc; #endif + #if MICROPY_PY_SYS_SETTRACE + rc->line_of_definition = emit->last_source_line; + #endif } // unsigned labels are relative to ip following this instruction, stored as 16 bits diff --git a/py/emitglue.c b/py/emitglue.c index 483a47025b122..d30a1e6741f4e 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -34,6 +34,7 @@ #include "py/emitglue.h" #include "py/runtime0.h" #include "py/bc.h" +#include "py/profile.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) @@ -52,6 +53,9 @@ mp_uint_t mp_verbose_flag = 0; mp_raw_code_t *mp_emit_glue_new_raw_code(void) { mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1); rc->kind = MP_CODE_RESERVED; + #if MICROPY_PY_SYS_SETTRACE + rc->line_of_definition = 0; + #endif return rc; } @@ -75,6 +79,11 @@ void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, rc->n_raw_code = n_raw_code; #endif + #if MICROPY_PY_SYS_SETTRACE + mp_bytecode_prelude_t *prelude = &rc->prelude; + mp_prof_extract_prelude(code, prelude); + #endif + #ifdef DEBUG_PRINT #if !MICROPY_DEBUG_PRINTERS const size_t len = 0; @@ -172,6 +181,12 @@ mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_ar if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { ((mp_obj_base_t*)MP_OBJ_TO_PTR(fun))->type = &mp_type_gen_wrap; } + + #if MICROPY_PY_SYS_SETTRACE + mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t *)MP_OBJ_TO_PTR(fun); + self_fun->rc = rc; + #endif + break; } diff --git a/py/emitglue.h b/py/emitglue.h index b67d49ed6d23a..a5411dc2e205f 100644 --- a/py/emitglue.h +++ b/py/emitglue.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_PY_EMITGLUE_H #include "py/obj.h" +#include "py/bc.h" // These variables and functions glue the code emitters to the runtime. @@ -63,6 +64,14 @@ typedef struct _mp_raw_code_t { size_t fun_data_len; uint16_t n_obj; uint16_t n_raw_code; + #if MICROPY_PY_SYS_SETTRACE + mp_bytecode_prelude_t prelude; + // line_of_definition is a Python source line where the raw_code was + // created e.g. MP_BC_MAKE_FUNCTION. This is different from lineno info + // stored in prelude, which provides line number for first statement of + // a function. Required to properly implement "call" trace event. + mp_uint_t line_of_definition; + #endif #if MICROPY_EMIT_MACHINE_CODE uint16_t prelude_offset; uint16_t n_qstr; diff --git a/py/modsys.c b/py/modsys.c index 3a91393812265..4886419d0edb6 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -35,6 +35,11 @@ #include "py/smallint.h" #include "py/runtime.h" +#if MICROPY_PY_SYS_SETTRACE +#include "py/objmodule.h" +#include "py/profile.h" +#endif + #if MICROPY_PY_SYS // defined per port; type of these is irrelevant, just need pointer @@ -156,6 +161,14 @@ STATIC mp_obj_t mp_sys_atexit(mp_obj_t obj) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_atexit_obj, mp_sys_atexit); #endif +#if MICROPY_PY_SYS_SETTRACE +// settrace(tracefunc): Set the system’s trace function. +STATIC mp_obj_t mp_sys_settrace(mp_obj_t obj) { + return mp_prof_settrace(obj); +} +MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_settrace_obj, mp_sys_settrace); +#endif // MICROPY_PY_SYS_SETTRACE + STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) }, @@ -190,6 +203,10 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mp_sys_exit_obj) }, #endif + #if MICROPY_PY_SYS_SETTRACE + { MP_ROM_QSTR(MP_QSTR_settrace), MP_ROM_PTR(&mp_sys_settrace_obj) }, + #endif + #if MICROPY_PY_SYS_STDFILES { MP_ROM_QSTR(MP_QSTR_stdin), MP_ROM_PTR(&mp_sys_stdin_obj) }, { MP_ROM_QSTR(MP_QSTR_stdout), MP_ROM_PTR(&mp_sys_stdout_obj) }, diff --git a/py/mpconfig.h b/py/mpconfig.h index 57dec3cf266b1..64dadde92d0c7 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1171,6 +1171,11 @@ typedef double mp_float_t; #define MICROPY_PY_SYS_ATEXIT (0) #endif +// Whether to provide "sys.settrace" function +#ifndef MICROPY_PY_SYS_SETTRACE +#define MICROPY_PY_SYS_SETTRACE (0) +#endif + // Whether to provide "sys.getsizeof" function #ifndef MICROPY_PY_SYS_GETSIZEOF #define MICROPY_PY_SYS_GETSIZEOF (0) @@ -1571,4 +1576,14 @@ typedef double mp_float_t; # define MP_WARN_CAT(x) (NULL) #endif +// Feature dependency check. +#if MICROPY_PY_SYS_SETTRACE +#if !MICROPY_PERSISTENT_CODE_SAVE +#error "MICROPY_PY_SYS_SETTRACE requires MICROPY_PERSISTENT_CODE_SAVE to be enabled" +#endif +#if MICROPY_COMP_CONST +#error "MICROPY_PY_SYS_SETTRACE requires MICROPY_COMP_CONST to be disabled" +#endif +#endif + #endif // MICROPY_INCLUDED_PY_MPCONFIG_H diff --git a/py/mpstate.h b/py/mpstate.h index 83fea3eb41d81..aba32084d53b6 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -253,6 +253,12 @@ typedef struct _mp_state_thread_t { mp_obj_dict_t *dict_globals; nlr_buf_t *nlr_top; + + #if MICROPY_PY_SYS_SETTRACE + mp_obj_t prof_trace_callback; + bool prof_callback_is_executing; + struct _mp_code_state_t *current_code_state; + #endif } mp_state_thread_t; // This structure combines the above 3 structures. diff --git a/py/objfun.h b/py/objfun.h index 257b8a65a7381..905b5dbca6d19 100644 --- a/py/objfun.h +++ b/py/objfun.h @@ -33,6 +33,9 @@ typedef struct _mp_obj_fun_bc_t { mp_obj_dict_t *globals; // the context within which this function was defined const byte *bytecode; // bytecode for the function const mp_uint_t *const_table; // constant table + #if MICROPY_PY_SYS_SETTRACE + const struct _mp_raw_code_t *rc; + #endif // the following extra_args array is allocated space to take (in order): // - values of positional default args (if any) // - a single slot for default kw args dict (if it has them) diff --git a/py/py.mk b/py/py.mk index 10beb29e45084..d60e694ec21fb 100644 --- a/py/py.mk +++ b/py/py.mk @@ -86,6 +86,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ stackctrl.o \ argcheck.o \ warning.o \ + profile.o \ map.o \ obj.o \ objarray.o \ diff --git a/py/runtime.c b/py/runtime.c index d81321e86282e..ecbdff2bab6e8 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -125,6 +125,12 @@ void mp_init(void) { MP_STATE_VM(sys_exitfunc) = mp_const_none; #endif + #if MICROPY_PY_SYS_SETTRACE + MP_STATE_THREAD(prof_trace_callback) = MP_OBJ_NULL; + MP_STATE_THREAD(prof_callback_is_executing) = false; + MP_STATE_THREAD(current_code_state) = NULL; + #endif + #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif diff --git a/py/vm.c b/py/vm.c index 0bc20346139b0..9abad8d83fe7b 100644 --- a/py/vm.c +++ b/py/vm.c @@ -34,6 +34,7 @@ #include "py/runtime.h" #include "py/bc0.h" #include "py/bc.h" +#include "py/profile.h" #if 0 #define TRACE(ip) printf("sp=%d ", (int)(sp - &code_state->state[0] + 1)); mp_bytecode_print2(ip, 1, code_state->fun_bc->const_table); @@ -108,6 +109,55 @@ exc_sp--; /* pop back to previous exception handler */ \ CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */ +#if MICROPY_PY_SYS_SETTRACE + +#define FRAME_SETUP() do { \ + assert(code_state != code_state->prev_state); \ + MP_STATE_THREAD(current_code_state) = code_state; \ + assert(code_state != code_state->prev_state); \ +} while(0) + +#define FRAME_ENTER() do { \ + assert(code_state != code_state->prev_state); \ + code_state->prev_state = MP_STATE_THREAD(current_code_state); \ + assert(code_state != code_state->prev_state); \ + if (!mp_prof_is_executing) { \ + mp_prof_frame_enter(code_state); \ + } \ +} while(0) + +#define FRAME_LEAVE() do { \ + assert(code_state != code_state->prev_state); \ + MP_STATE_THREAD(current_code_state) = code_state->prev_state; \ + assert(code_state != code_state->prev_state); \ +} while(0) + +#define FRAME_UPDATE() do { \ + assert(MP_STATE_THREAD(current_code_state) == code_state); \ + if (!mp_prof_is_executing) { \ + code_state->frame = MP_OBJ_TO_PTR(mp_prof_frame_update(code_state)); \ + } \ +} while(0) + +#define TRACE_TICK(current_ip, current_sp, is_exception) do { \ + assert(code_state != code_state->prev_state); \ + assert(MP_STATE_THREAD(current_code_state) == code_state); \ + if (!mp_prof_is_executing && code_state->frame && MP_STATE_THREAD(prof_trace_callback)) { \ + MP_PROF_INSTR_DEBUG_PRINT(code_state->ip); \ + } \ + if (!mp_prof_is_executing && code_state->frame && code_state->frame->callback) { \ + mp_prof_instr_tick(code_state, is_exception); \ + } \ +} while(0) + +#else // MICROPY_PY_SYS_SETTRACE +#define FRAME_SETUP() +#define FRAME_ENTER() +#define FRAME_LEAVE() +#define FRAME_UPDATE() +#define TRACE_TICK(current_ip, current_sp, is_exception) +#endif // MICROPY_PY_SYS_SETTRACE + // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc) // sp points to bottom of stack which grows up // returns: @@ -128,6 +178,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp #define DISPATCH() do { \ TRACE(ip); \ MARK_EXC_IP_GLOBAL(); \ + TRACE_TICK(ip, sp, false); \ goto *entry_table[*ip++]; \ } while (0) #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check @@ -149,6 +200,13 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp #if MICROPY_STACKLESS run_code_state: ; #endif +FRAME_ENTER(); + +#if MICROPY_STACKLESS +run_code_state_from_return: ; +#endif +FRAME_SETUP(); + // Pointers which are constant for particular invocation of mp_execute_bytecode() mp_obj_t * /*const*/ fastn; mp_exc_stack_t * /*const*/ exc_stack; @@ -198,6 +256,7 @@ run_code_state: ; #else TRACE(ip); MARK_EXC_IP_GLOBAL(); + TRACE_TICK(ip, sp, false); switch (*ip++) { #endif @@ -323,6 +382,7 @@ run_code_state: ; #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE ENTRY(MP_BC_LOAD_ATTR): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; SET_TOP(mp_load_attr(TOP(), qst)); @@ -330,6 +390,7 @@ run_code_state: ; } #else ENTRY(MP_BC_LOAD_ATTR): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t top = TOP(); @@ -415,6 +476,7 @@ run_code_state: ; #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE ENTRY(MP_BC_STORE_ATTR): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_store_attr(sp[0], qst, sp[-1]); @@ -428,6 +490,7 @@ run_code_state: ; // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND // in the fast-path below, because that store could override a property. ENTRY(MP_BC_STORE_ATTR): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t top = TOP(); @@ -738,6 +801,7 @@ unwind_jump:; } ENTRY(MP_BC_FOR_ITER): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward code_state->sp = sp; @@ -753,6 +817,12 @@ unwind_jump:; ip += ulab; // jump to after for-block } else { PUSH(value); // push the next iteration value + #if MICROPY_PY_SYS_SETTRACE + // LINE event should trigger for every iteration so invalidate last trigger + if (code_state->frame) { + code_state->frame->lineno = 0; + } + #endif } DISPATCH(); } @@ -887,6 +957,7 @@ unwind_jump:; } ENTRY(MP_BC_CALL_FUNCTION): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional @@ -921,6 +992,7 @@ unwind_jump:; } ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional @@ -966,6 +1038,7 @@ unwind_jump:; } ENTRY(MP_BC_CALL_METHOD): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional @@ -1004,6 +1077,7 @@ unwind_jump:; } ENTRY(MP_BC_CALL_METHOD_VAR_KW): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_UINT; // unum & 0xff == n_positional @@ -1096,9 +1170,10 @@ unwind_jump:; #endif code_state = new_code_state; *code_state->sp = res; - goto run_code_state; + goto run_code_state_from_return; } #endif + FRAME_LEAVE(); return MP_VM_RETURN_NORMAL; ENTRY(MP_BC_RAISE_VARARGS): { @@ -1136,6 +1211,7 @@ unwind_jump:; code_state->ip = ip; code_state->sp = sp; code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, 0); + FRAME_LEAVE(); return MP_VM_RETURN_YIELD; ENTRY(MP_BC_YIELD_FROM): { @@ -1192,6 +1268,7 @@ unwind_jump:; } ENTRY(MP_BC_IMPORT_NAME): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t obj = POP(); @@ -1200,6 +1277,7 @@ unwind_jump:; } ENTRY(MP_BC_IMPORT_FROM): { + FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t obj = mp_import_from(TOP(), qst); @@ -1266,6 +1344,7 @@ unwind_jump:; mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "opcode"); nlr_pop(); code_state->state[0] = obj; + FRAME_LEAVE(); return MP_VM_RETURN_EXCEPTION; } @@ -1356,6 +1435,13 @@ unwind_jump:; } } + #if MICROPY_PY_SYS_SETTRACE + // Exceptions are traced here + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_Exception))) { + TRACE_TICK(code_state->ip, code_state->sp, true /* yes, it's an exception */); + } + #endif + #if MICROPY_STACKLESS unwind_loop: #endif @@ -1438,6 +1524,7 @@ unwind_jump:; // propagate exception to higher level // Note: ip and sp don't have usable values at this point code_state->state[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // put exception here because sp is invalid + FRAME_LEAVE(); return MP_VM_RETURN_EXCEPTION; } } From 498e35219e1f54243ff6d650781c525e20cad9b1 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Wed, 14 Aug 2019 16:11:25 +0200 Subject: [PATCH 0386/1299] tests: Add tests for sys.settrace feature. --- tests/cmdline/cmd_showbc.py.exp | 3 + tests/misc/sys_settrace_features.py | 91 ++++++++ tests/misc/sys_settrace_generator.py | 62 ++++++ tests/misc/sys_settrace_generator.py.exp | 195 ++++++++++++++++++ tests/misc/sys_settrace_loop.py | 51 +++++ tests/misc/sys_settrace_loop.py.exp | 72 +++++++ .../misc/sys_settrace_subdir/trace_generic.py | 82 ++++++++ .../sys_settrace_subdir/trace_importme.py | 24 +++ tools/tinytest-codegen.py | 4 + 9 files changed, 584 insertions(+) create mode 100644 tests/misc/sys_settrace_features.py create mode 100644 tests/misc/sys_settrace_generator.py create mode 100644 tests/misc/sys_settrace_generator.py.exp create mode 100644 tests/misc/sys_settrace_loop.py create mode 100644 tests/misc/sys_settrace_loop.py.exp create mode 100644 tests/misc/sys_settrace_subdir/trace_generic.py create mode 100644 tests/misc/sys_settrace_subdir/trace_importme.py diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 8d5d2ffe302ce..36f0404388e55 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -417,6 +417,7 @@ arg names: (N_STATE 1) (N_EXC_STACK 0) bc=-1 line=1 +######## bc=13 line=149 00 LOAD_NAME __name__ (cache=0) 04 STORE_NAME __module__ @@ -450,6 +451,7 @@ arg names: * * * (N_EXC_STACK 0) bc=-\\d\+ line=1 bc=0 line=59 +######## 00 LOAD_NULL 01 LOAD_FAST 2 02 LOAD_NULL @@ -473,6 +475,7 @@ arg names: * * * (N_EXC_STACK 0) bc=-\\d\+ line=1 bc=0 line=60 +######## 00 BUILD_LIST 0 02 LOAD_FAST 2 03 GET_ITER_STACK diff --git a/tests/misc/sys_settrace_features.py b/tests/misc/sys_settrace_features.py new file mode 100644 index 0000000000000..932e430de740e --- /dev/null +++ b/tests/misc/sys_settrace_features.py @@ -0,0 +1,91 @@ +import sys + +try: + sys.settrace +except AttributeError: + print("SKIP") + raise SystemExit + +def print_stacktrace(frame, level=0): + # Ignore CPython specific helpers. + if frame.f_globals['__name__'].find('importlib') != -1: + print_stacktrace(frame.f_back, level) + return + + print("%2d: %s@%s:%s => %s:%d" % ( + level, " ", + frame.f_globals['__name__'], + frame.f_code.co_name, + # reduce full path to some pseudo-relative + 'misc' + ''.join(frame.f_code.co_filename.split('tests/misc')[-1:]), + frame.f_lineno, + )) + + if frame.f_back: + print_stacktrace(frame.f_back, level + 1) + +class _Prof: + trace_count = 0; + + def trace_tick(self, frame, event, arg): + self.trace_count += 1 + print_stacktrace(frame) + +__prof__ = _Prof() + +alice_handler_set = False +def trace_tick_handler_alice(frame, event, arg): + print("### trace_handler::Alice event:", event) + __prof__.trace_tick(frame, event, arg) + return trace_tick_handler_alice + +bob_handler_set = False +def trace_tick_handler_bob(frame, event, arg): + print("### trace_handler::Bob event:", event) + __prof__.trace_tick(frame, event, arg) + return trace_tick_handler_bob + +def trace_tick_handler(frame, event, arg): + # Ignore CPython specific helpers. + if frame.f_globals['__name__'].find('importlib') != -1: + return + + print("### trace_handler::main event:", event) + __prof__.trace_tick(frame, event, arg) + + if frame.f_code.co_name != 'factorial': + return trace_tick_handler + + global alice_handler_set + if event == 'call' and not alice_handler_set: + alice_handler_set = True + return trace_tick_handler_alice + + global bob_handler_set + if event == 'call' and not bob_handler_set: + bob_handler_set = True + return trace_tick_handler_bob + + return trace_tick_handler + +def factorial(n): + if n == 0: + return 1 + else: + return n * factorial(n - 1) + +def do_tests(): + # These commands are here to demonstrate some execution being traced. + print("Who loves the sun?") + print("Not every-", factorial(3)) + + from sys_settrace_subdir import trace_generic + trace_generic.run_tests() + return + +sys.settrace(trace_tick_handler) +do_tests() +sys.settrace(None) + +print("\n------------------ script exited ------------------") +print("Total traces executed: ", __prof__.trace_count) diff --git a/tests/misc/sys_settrace_generator.py b/tests/misc/sys_settrace_generator.py new file mode 100644 index 0000000000000..e955d6b626627 --- /dev/null +++ b/tests/misc/sys_settrace_generator.py @@ -0,0 +1,62 @@ +# test sys.settrace with generators + +import sys + +try: + sys.settrace +except AttributeError: + print("SKIP") + raise SystemExit + +def print_stacktrace(frame, level=0): + print("%2d: %s@%s:%s => %s:%d" % ( + level, " ", + frame.f_globals['__name__'], + frame.f_code.co_name, + # reduce full path to some pseudo-relative + 'misc' + ''.join(frame.f_code.co_filename.split('tests/misc')[-1:]), + frame.f_lineno, + )) + + if frame.f_back: + print_stacktrace(frame.f_back, level + 1) + +trace_count = 0 + +def trace_tick_handler(frame, event, arg): + global trace_count + print("### trace_handler::main event:", event) + trace_count += 1 + print_stacktrace(frame) + return trace_tick_handler + +def test_generator(): + def make_gen(): + yield 1<<0 + yield 1<<1 + yield 1<<2 + return 1<<3 + + gen = make_gen() + r = 0 + try: + + r += gen.send(None) + + while True: + + r += gen.send(None) + + except StopIteration as e: + print("test_generator", r, e) + + gen = make_gen() + r = 0 + for i in gen: + r += i + print(r) + +sys.settrace(trace_tick_handler) +test_generator() +sys.settrace(None) +print("Total traces executed: ", trace_count) diff --git a/tests/misc/sys_settrace_generator.py.exp b/tests/misc/sys_settrace_generator.py.exp new file mode 100644 index 0000000000000..5329cdfe71e24 --- /dev/null +++ b/tests/misc/sys_settrace_generator.py.exp @@ -0,0 +1,195 @@ +### trace_handler::main event: call + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:33 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:34 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:40 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:41 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:42 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:34 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:44 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: exception + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:48 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:50 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:51 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +test_generator 7 8 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:53 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:54 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:34 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:56 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:35 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:56 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:36 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:56 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: call + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:37 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: return + 0: @__main__:make_gen => miscmisc/sys_settrace_generator.py:38 + 1: @__main__:test_generator => miscmisc/sys_settrace_generator.py:55 + 2: @__main__: => miscmisc/sys_settrace_generator.py:60 +### trace_handler::main event: line + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:57 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +7 +### trace_handler::main event: return + 0: @__main__:test_generator => miscmisc/sys_settrace_generator.py:57 + 1: @__main__: => miscmisc/sys_settrace_generator.py:60 +Total traces executed: 54 diff --git a/tests/misc/sys_settrace_loop.py b/tests/misc/sys_settrace_loop.py new file mode 100644 index 0000000000000..9ae0f41a1d685 --- /dev/null +++ b/tests/misc/sys_settrace_loop.py @@ -0,0 +1,51 @@ +# test sys.settrace with while and for loops + +import sys + +try: + sys.settrace +except AttributeError: + print("SKIP") + raise SystemExit + +def print_stacktrace(frame, level=0): + print("%2d: %s@%s:%s => %s:%d" % ( + level, " ", + frame.f_globals['__name__'], + frame.f_code.co_name, + # reduce full path to some pseudo-relative + 'misc' + ''.join(frame.f_code.co_filename.split('tests/misc')[-1:]), + frame.f_lineno, + )) + + if frame.f_back: + print_stacktrace(frame.f_back, level + 1) + +trace_count = 0 + +def trace_tick_handler(frame, event, arg): + global trace_count + print("### trace_handler::main event:", event) + trace_count += 1 + print_stacktrace(frame) + return trace_tick_handler + +def test_loop(): + # for loop + r = 0 + for i in range(3): + r += i + print("test_for_loop", r) + + # while loop + r = 0 + i = 0 + while i < 3: + r += i + i += 1 + print("test_while_loop", i) + +sys.settrace(trace_tick_handler) +test_loop() +sys.settrace(None) +print("Total traces executed: ", trace_count) diff --git a/tests/misc/sys_settrace_loop.py.exp b/tests/misc/sys_settrace_loop.py.exp new file mode 100644 index 0000000000000..3d3da5b6f762b --- /dev/null +++ b/tests/misc/sys_settrace_loop.py.exp @@ -0,0 +1,72 @@ +### trace_handler::main event: call + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:33 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:35 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:36 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:37 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:38 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +test_for_loop 3 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:41 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:42 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:43 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:44 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:44 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:44 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:45 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +### trace_handler::main event: line + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:46 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +test_while_loop 3 +### trace_handler::main event: return + 0: @__main__:test_loop => miscmisc/sys_settrace_loop.py:46 + 1: @__main__: => miscmisc/sys_settrace_loop.py:49 +Total traces executed: 23 diff --git a/tests/misc/sys_settrace_subdir/trace_generic.py b/tests/misc/sys_settrace_subdir/trace_generic.py new file mode 100644 index 0000000000000..3239a019c781a --- /dev/null +++ b/tests/misc/sys_settrace_subdir/trace_generic.py @@ -0,0 +1,82 @@ +print("Now comes the language constructions tests.") + +# function +def test_func(): + def test_sub_func(): + print("test_function") + + test_sub_func() + +# closure +def test_closure(msg): + + def make_closure(): + print(msg) + + return make_closure + +# exception +def test_exception(): + try: + raise Exception("test_exception") + + except Exception: + pass + + finally: + pass + +# listcomp +def test_listcomp(): + print("test_listcomp", [x for x in range(3)]) + +# lambda +def test_lambda(): + func_obj_1 = lambda a, b: a + b + print(func_obj_1(10, 20)) + +# import +def test_import(): + from sys_settrace_subdir import trace_importme + trace_importme.dummy() + trace_importme.saysomething() + +# class +class TLClass(): + def method(): + pass + pass + +def test_class(): + class TestClass: + __anynum = -9 + def method(self): + print("test_class_method") + self.__anynum += 1 + + def prprty_getter(self): + return self.__anynum + + def prprty_setter(self, what): + self.__anynum = what + + prprty = property(prprty_getter, prprty_setter) + + cls = TestClass() + cls.method() + print("test_class_property", cls.prprty) + cls.prprty = 12 + print("test_class_property", cls.prprty) + + +def run_tests(): + test_func() + test_closure_inst = test_closure("test_closure") + test_closure_inst() + test_exception() + test_listcomp() + test_lambda() + test_class() + test_import() + +print("And it's done!") diff --git a/tests/misc/sys_settrace_subdir/trace_importme.py b/tests/misc/sys_settrace_subdir/trace_importme.py new file mode 100644 index 0000000000000..0ff7c6d5bb985 --- /dev/null +++ b/tests/misc/sys_settrace_subdir/trace_importme.py @@ -0,0 +1,24 @@ +print("Yep, I got imported.") + +try: + x = const(1) +except NameError: + print('const not defined') + +const = lambda x: x + +_CNT01 = "CONST01" +_CNT02 = const(123) +A123 = const(123) +a123 = const(123) + +def dummy(): + return False + +def saysomething(): + print("There, I said it.") + +def neverexecuted(): + print("Never got here!") + +print("Yep, got here") diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index bdace1c8b5a83..7580522ee671f 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -83,6 +83,10 @@ def script_to_map(test_file): 'micropython/meminfo.py', # needs sys stdfiles 'misc/print_exception.py', + # settrace .exp files are too large + 'misc/sys_settrace_loop.py', + 'misc/sys_settrace_generator.py', + 'misc/sys_settrace_features.py', ) output = [] From b295df4b081dbe6f8aee2e54d1bea019a1b97236 Mon Sep 17 00:00:00 2001 From: Milan Rossa Date: Wed, 14 Aug 2019 16:12:54 +0200 Subject: [PATCH 0387/1299] py/profile: Add debugging for sys.settrace feature. --- py/profile.c | 543 +++++++++++++++++++++++++++++++++++++++++++++++++++ py/profile.h | 10 + 2 files changed, 553 insertions(+) diff --git a/py/profile.c b/py/profile.c index 39578f6dcd5fd..8c4feaa11cac3 100644 --- a/py/profile.c +++ b/py/profile.c @@ -438,4 +438,547 @@ mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception) { return top; } +/******************************************************************************/ +// DEBUG + +// This section is for debugging the settrace feature itself, and is not intended +// to be included in production/release builds. The code structure for this block +// was taken from py/showbc.c and should not be used as a reference. To enable +// this debug feature enable MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE in py/profile.h. +#if MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE + +#include "runtime0.h" + +#define DECODE_UINT { \ + unum = 0; \ + do { \ + unum = (unum << 7) + (*ip & 0x7f); \ + } while ((*ip++ & 0x80) != 0); \ +} +#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0) +#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0) + +#define DECODE_QSTR \ + qst = ip[0] | ip[1] << 8; \ + ip += 2; +#define DECODE_PTR \ + DECODE_UINT; \ + ptr = (const byte*)const_table[unum] +#define DECODE_OBJ \ + DECODE_UINT; \ + obj = (mp_obj_t)const_table[unum] + +typedef struct _mp_dis_instruction_t { + mp_uint_t qstr_opname; + mp_uint_t arg; + mp_obj_t argobj; + mp_obj_t argobjex_cache; +} mp_dis_instruction_t; + +STATIC const byte *mp_prof_opcode_decode(const byte *ip, const mp_uint_t *const_table, mp_dis_instruction_t *instruction) { + mp_uint_t unum; + const byte* ptr; + mp_obj_t obj; + qstr qst; + + instruction->qstr_opname = MP_QSTR_; + instruction->arg = 0; + instruction->argobj= mp_const_none; + instruction->argobjex_cache = mp_const_none; + + switch (*ip++) { + case MP_BC_LOAD_CONST_FALSE: + instruction->qstr_opname = MP_QSTR_LOAD_CONST_FALSE; + break; + + case MP_BC_LOAD_CONST_NONE: + instruction->qstr_opname = MP_QSTR_LOAD_CONST_NONE; + break; + + case MP_BC_LOAD_CONST_TRUE: + instruction->qstr_opname = MP_QSTR_LOAD_CONST_TRUE; + break; + + case MP_BC_LOAD_CONST_SMALL_INT: { + mp_int_t num = 0; + if ((ip[0] & 0x40) != 0) { + // Number is negative + num--; + } + do { + num = (num << 7) | (*ip & 0x7f); + } while ((*ip++ & 0x80) != 0); + instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT; + instruction->arg = num; + break; + } + + case MP_BC_LOAD_CONST_STRING: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_LOAD_CONST_STRING; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_LOAD_CONST_OBJ: + DECODE_OBJ; + instruction->qstr_opname = MP_QSTR_LOAD_CONST_OBJ; + instruction->arg = unum; + instruction->argobj= obj; + break; + + case MP_BC_LOAD_NULL: + instruction->qstr_opname = MP_QSTR_LOAD_NULL; + break; + + case MP_BC_LOAD_FAST_N: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_LOAD_FAST_N; + instruction->arg = unum; + break; + + case MP_BC_LOAD_DEREF: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_LOAD_DEREF; + instruction->arg = unum; + break; + + case MP_BC_LOAD_NAME: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_LOAD_NAME; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); + } + break; + + case MP_BC_LOAD_GLOBAL: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_LOAD_GLOBAL; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); + } + break; + + case MP_BC_LOAD_ATTR: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_LOAD_ATTR; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); + } + break; + + case MP_BC_LOAD_METHOD: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_LOAD_METHOD; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_LOAD_SUPER_METHOD: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_LOAD_SUPER_METHOD; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_LOAD_BUILD_CLASS: + instruction->qstr_opname = MP_QSTR_LOAD_BUILD_CLASS; + break; + + case MP_BC_LOAD_SUBSCR: + instruction->qstr_opname = MP_QSTR_LOAD_SUBSCR; + break; + + case MP_BC_STORE_FAST_N: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_STORE_FAST_N; + instruction->arg = unum; + break; + + case MP_BC_STORE_DEREF: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_STORE_DEREF; + instruction->arg = unum; + break; + + case MP_BC_STORE_NAME: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_STORE_NAME; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_STORE_GLOBAL: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_STORE_GLOBAL; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_STORE_ATTR: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_STORE_ATTR; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) { + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(*ip++); + } + break; + + case MP_BC_STORE_SUBSCR: + instruction->qstr_opname = MP_QSTR_STORE_SUBSCR; + break; + + case MP_BC_DELETE_FAST: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_DELETE_FAST; + instruction->arg = unum; + break; + + case MP_BC_DELETE_DEREF: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_DELETE_DEREF; + instruction->arg = unum; + break; + + case MP_BC_DELETE_NAME: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_DELETE_NAME; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_DELETE_GLOBAL: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_DELETE_GLOBAL; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_DUP_TOP: + instruction->qstr_opname = MP_QSTR_DUP_TOP; + break; + + case MP_BC_DUP_TOP_TWO: + instruction->qstr_opname = MP_QSTR_DUP_TOP_TWO; + break; + + case MP_BC_POP_TOP: + instruction->qstr_opname = MP_QSTR_POP_TOP; + break; + + case MP_BC_ROT_TWO: + instruction->qstr_opname = MP_QSTR_ROT_TWO; + break; + + case MP_BC_ROT_THREE: + instruction->qstr_opname = MP_QSTR_ROT_THREE; + break; + + case MP_BC_JUMP: + DECODE_SLABEL; + instruction->qstr_opname = MP_QSTR_JUMP; + instruction->arg = unum; + break; + + case MP_BC_POP_JUMP_IF_TRUE: + DECODE_SLABEL; + instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_TRUE; + instruction->arg = unum; + break; + + case MP_BC_POP_JUMP_IF_FALSE: + DECODE_SLABEL; + instruction->qstr_opname = MP_QSTR_POP_JUMP_IF_FALSE; + instruction->arg = unum; + break; + + case MP_BC_JUMP_IF_TRUE_OR_POP: + DECODE_SLABEL; + instruction->qstr_opname = MP_QSTR_JUMP_IF_TRUE_OR_POP; + instruction->arg = unum; + break; + + case MP_BC_JUMP_IF_FALSE_OR_POP: + DECODE_SLABEL; + instruction->qstr_opname = MP_QSTR_JUMP_IF_FALSE_OR_POP; + instruction->arg = unum; + break; + + case MP_BC_SETUP_WITH: + DECODE_ULABEL; // loop-like labels are always forward + instruction->qstr_opname = MP_QSTR_SETUP_WITH; + instruction->arg = unum; + break; + + case MP_BC_WITH_CLEANUP: + instruction->qstr_opname = MP_QSTR_WITH_CLEANUP; + break; + + case MP_BC_UNWIND_JUMP: + DECODE_SLABEL; + instruction->qstr_opname = MP_QSTR_UNWIND_JUMP; + instruction->arg = unum; + break; + + case MP_BC_SETUP_EXCEPT: + DECODE_ULABEL; // except labels are always forward + instruction->qstr_opname = MP_QSTR_SETUP_EXCEPT; + instruction->arg = unum; + break; + + case MP_BC_SETUP_FINALLY: + DECODE_ULABEL; // except labels are always forward + instruction->qstr_opname = MP_QSTR_SETUP_FINALLY; + instruction->arg = unum; + break; + + case MP_BC_END_FINALLY: + // if TOS is an exception, reraises the exception (3 values on TOS) + // if TOS is an integer, does something else + // if TOS is None, just pops it and continues + // else error + instruction->qstr_opname = MP_QSTR_END_FINALLY; + break; + + case MP_BC_GET_ITER: + instruction->qstr_opname = MP_QSTR_GET_ITER; + break; + + case MP_BC_GET_ITER_STACK: + instruction->qstr_opname = MP_QSTR_GET_ITER_STACK; + break; + + case MP_BC_FOR_ITER: + DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward + instruction->qstr_opname = MP_QSTR_FOR_ITER; + instruction->arg = unum; + break; + + case MP_BC_BUILD_TUPLE: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_BUILD_TUPLE; + instruction->arg = unum; + break; + + case MP_BC_BUILD_LIST: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_BUILD_LIST; + instruction->arg = unum; + break; + + case MP_BC_BUILD_MAP: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_BUILD_MAP; + instruction->arg = unum; + break; + + case MP_BC_STORE_MAP: + instruction->qstr_opname = MP_QSTR_STORE_MAP; + break; + + case MP_BC_BUILD_SET: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_BUILD_SET; + instruction->arg = unum; + break; + + #if MICROPY_PY_BUILTINS_SLICE + case MP_BC_BUILD_SLICE: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_BUILD_SLICE; + instruction->arg = unum; + break; + #endif + + case MP_BC_STORE_COMP: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_STORE_COMP; + instruction->arg = unum; + break; + + case MP_BC_UNPACK_SEQUENCE: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_UNPACK_SEQUENCE; + instruction->arg = unum; + break; + + case MP_BC_UNPACK_EX: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_UNPACK_EX; + instruction->arg = unum; + break; + + case MP_BC_MAKE_FUNCTION: + DECODE_PTR; + instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION; + instruction->arg = unum; + instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); + break; + + case MP_BC_MAKE_FUNCTION_DEFARGS: + DECODE_PTR; + instruction->qstr_opname = MP_QSTR_MAKE_FUNCTION_DEFARGS; + instruction->arg = unum; + instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); + break; + + case MP_BC_MAKE_CLOSURE: { + DECODE_PTR; + mp_uint_t n_closed_over = *ip++; + instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE; + instruction->arg = unum; + instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over); + break; + } + + case MP_BC_MAKE_CLOSURE_DEFARGS: { + DECODE_PTR; + mp_uint_t n_closed_over = *ip++; + instruction->qstr_opname = MP_QSTR_MAKE_CLOSURE_DEFARGS; + instruction->arg = unum; + instruction->argobj= mp_obj_new_int_from_ull((uint64_t)ptr); + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT(n_closed_over); + break; + } + + case MP_BC_CALL_FUNCTION: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_CALL_FUNCTION; + instruction->arg = unum & 0xff; + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); + break; + + case MP_BC_CALL_FUNCTION_VAR_KW: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_CALL_FUNCTION_VAR_KW; + instruction->arg = unum & 0xff; + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); + break; + + case MP_BC_CALL_METHOD: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_CALL_METHOD; + instruction->arg = unum & 0xff; + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); + break; + + case MP_BC_CALL_METHOD_VAR_KW: + DECODE_UINT; + instruction->qstr_opname = MP_QSTR_CALL_METHOD_VAR_KW; + instruction->arg = unum & 0xff; + instruction->argobjex_cache = MP_OBJ_NEW_SMALL_INT((unum >> 8) & 0xff); + break; + + case MP_BC_RETURN_VALUE: + instruction->qstr_opname = MP_QSTR_RETURN_VALUE; + break; + + case MP_BC_RAISE_VARARGS: + unum = *ip++; + instruction->qstr_opname = MP_QSTR_RAISE_VARARGS; + instruction->arg = unum; + break; + + case MP_BC_YIELD_VALUE: + instruction->qstr_opname = MP_QSTR_YIELD_VALUE; + break; + + case MP_BC_YIELD_FROM: + instruction->qstr_opname = MP_QSTR_YIELD_FROM; + break; + + case MP_BC_IMPORT_NAME: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_IMPORT_NAME; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_IMPORT_FROM: + DECODE_QSTR; + instruction->qstr_opname = MP_QSTR_IMPORT_FROM; + instruction->arg = qst; + instruction->argobj= MP_OBJ_NEW_QSTR(qst); + break; + + case MP_BC_IMPORT_STAR: + instruction->qstr_opname = MP_QSTR_IMPORT_STAR; + break; + + default: + if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) { + instruction->qstr_opname = MP_QSTR_LOAD_CONST_SMALL_INT; + instruction->arg = (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16; + } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) { + instruction->qstr_opname = MP_QSTR_LOAD_FAST; + instruction->arg = (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI; + } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) { + instruction->qstr_opname = MP_QSTR_STORE_FAST; + instruction->arg = (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI; + } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) { + instruction->qstr_opname = MP_QSTR_UNARY_OP; + instruction->arg = (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI; + } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) { + mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI; + instruction->qstr_opname = MP_QSTR_BINARY_OP; + instruction->arg = op; + } else { + mp_printf(&mp_plat_print, "code %p, opcode 0x%02x not implemented\n", ip-1, ip[-1]); + assert(0); + return ip; + } + break; + } + + return ip; +} + +void mp_prof_print_instr(const byte* ip, mp_code_state_t *code_state) { + mp_dis_instruction_t _instruction, *instruction = &_instruction; + mp_prof_opcode_decode(ip, code_state->fun_bc->rc->const_table, instruction); + const mp_raw_code_t *rc = code_state->fun_bc->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + + mp_uint_t offset = ip - prelude->opcodes; + mp_printf(&mp_plat_print, "instr"); + + /* long path */ if (1) { + mp_printf(&mp_plat_print, + "@0x%p:%q:%q+0x%04x:%d", + ip, + prelude->qstr_source_file, + prelude->qstr_block_name, + offset, + mp_prof_bytecode_lineno(rc, offset) + ); + } + + /* bytecode */ if (0) { + mp_printf(&mp_plat_print, " %02x %02x %02x %02x", ip[0], ip[1], ip[2], ip[3]); + } + + mp_printf(&mp_plat_print, " 0x%02x %q [%d]", *ip, instruction->qstr_opname, instruction->arg); + + if (instruction->argobj != mp_const_none) { + mp_printf(&mp_plat_print, " $"); + mp_obj_print_helper(&mp_plat_print, instruction->argobj, PRINT_REPR); + } + if (instruction->argobjex_cache != mp_const_none) { + mp_printf(&mp_plat_print, " #"); + mp_obj_print_helper(&mp_plat_print, instruction->argobjex_cache, PRINT_REPR); + } + + mp_printf(&mp_plat_print, "\n"); +} + +#endif // MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE + #endif // MICROPY_PY_SYS_SETTRACE diff --git a/py/profile.h b/py/profile.h index 227634b564cc2..0293e262f0407 100644 --- a/py/profile.h +++ b/py/profile.h @@ -65,5 +65,15 @@ mp_obj_t mp_prof_frame_update(const mp_code_state_t *code_state); // For every VM instruction tick this function deduces events from the state mp_obj_t mp_prof_instr_tick(mp_code_state_t *code_state, bool is_exception); +// This section is for debugging the settrace feature itself, and is not intended +// to be included in production/release builds. +#define MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE 0 +#if MICROPY_PROF_INSTR_DEBUG_PRINT_ENABLE +void mp_prof_print_instr(const byte* ip, mp_code_state_t *code_state); +#define MP_PROF_INSTR_DEBUG_PRINT(current_ip) mp_prof_print_instr((current_ip), code_state) +#else +#define MP_PROF_INSTR_DEBUG_PRINT(current_ip) +#endif + #endif // MICROPY_PY_SYS_SETTRACE #endif // MICROPY_INCLUDED_PY_PROFILING_H From 060209240ba3a7fcf6338221417e363c10d6e147 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 20 Aug 2019 14:15:50 +1000 Subject: [PATCH 0388/1299] esp8266: Put new profile code in iROM. --- ports/esp8266/esp8266_common.ld | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp8266/esp8266_common.ld b/ports/esp8266/esp8266_common.ld index f4b4207f27e3d..bbbb1325e1147 100644 --- a/ports/esp8266/esp8266_common.ld +++ b/ports/esp8266/esp8266_common.ld @@ -110,6 +110,7 @@ SECTIONS *py/obj*.o*(.literal* .text*) *py/opmethods.o*(.literal* .text*) *py/parse*.o*(.literal* .text*) + *py/profile*.o*(.literal* .text*) *py/qstr.o*(.literal* .text*) *py/repl.o*(.literal* .text*) *py/runtime.o*(.literal* .text*) From 4691b43c8a245451c1f6eab2261a9433d694ef3e Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 24 Aug 2019 00:16:49 +1000 Subject: [PATCH 0389/1299] tools/mpy-tool.py: Add initial support for frozen with settrace. --- tools/mpy-tool.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 7938ea5dc8480..3d2a8fb7c6562 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -410,6 +410,22 @@ def freeze_module(self, qstr_links=(), type_sig=0): print(' .fun_data_len = %u,' % len(self.bytecode)) print(' .n_obj = %u,' % len(self.objs)) print(' .n_raw_code = %u,' % len(self.raw_codes)) + print(' #if MICROPY_PY_SYS_SETTRACE') + print(' .prelude = {') + print(' .n_state = %u,' % self.prelude[0]) + print(' .n_exc_stack = %u,' % self.prelude[1]) + print(' .scope_flags = %u,' % self.prelude[2]) + print(' .n_pos_args = %u,' % self.prelude[3]) + print(' .n_kwonly_args = %u,' % self.prelude[4]) + print(' .n_def_pos_args = %u,' % self.prelude[5]) + print(' .qstr_block_name = %s,' % self.simple_name.qstr_id) + print(' .qstr_source_file = %s,' % self.source_file.qstr_id) + print(' .line_info = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO + print(' .locals = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO + print(' .opcodes = fun_data_%s + %u,' % (self.escaped_name, self.ip)) + print(' },') + print(' .line_of_definition = %u,' % 0) # TODO + print(' #endif') print(' #if MICROPY_EMIT_MACHINE_CODE') print(' .prelude_offset = %u,' % self.prelude_offset) print(' .n_qstr = %u,' % len(qstr_links)) From 0b85b5b8b3357860c426cede526f48fdd84b56fd Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 27 Aug 2019 15:43:10 +1000 Subject: [PATCH 0390/1299] travis: Add new job to test unix port with sys.settrace enabled. --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index e319f095b13eb..72dbe138f7689 100644 --- a/.travis.yml +++ b/.travis.yml @@ -115,6 +115,17 @@ jobs: - make ${MAKEOPTS} -C ports/unix CC=clang CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1" - make ${MAKEOPTS} -C ports/unix CC=clang test + # unix with sys.settrace + - stage: test + env: NAME="unix port with sys.settrace build and tests" + script: + - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/unix MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-DMICROPY_PY_SYS_SETTRACE=1" test + - make ${MAKEOPTS} -C ports/unix clean + - make ${MAKEOPTS} -C ports/unix MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_USSL=0 CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1 -DMICROPY_PY_SYS_SETTRACE=1" test + after_failure: + - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) + # windows port via mingw - stage: test env: NAME="windows port build via mingw" From 12f13ee6346d8fd029fc2ecec06d50b5f7f6b252 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 13 Aug 2019 07:07:49 -0500 Subject: [PATCH 0391/1299] py/objtuple: Allow compatible subclasses of tuple in mp_obj_tuple_get. As part of this patch a private macro mp_obj_is_tuple_compatible is introduced to encapsulate the check, which is used in two locations. Fixes #5005. --- py/objtuple.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/py/objtuple.c b/py/objtuple.c index 39eb940236693..740e0795b3328 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -31,6 +31,9 @@ #include "py/objtuple.h" #include "py/runtime.h" +// type check is done on getiter method to allow tuple, namedtuple, attrtuple +#define mp_obj_is_tuple_compatible(o) (mp_obj_get_type(o)->getiter == mp_obj_tuple_getiter) + /******************************************************************************/ /* tuple */ @@ -101,8 +104,7 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg // Don't pass MP_BINARY_OP_NOT_EQUAL here STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { - // type check is done on getiter method to allow tuple, namedtuple, attrtuple - mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter); + mp_check_self(mp_obj_is_tuple_compatible(self_in)); mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); if (another_type->getiter != mp_obj_tuple_getiter) { @@ -249,7 +251,7 @@ mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) { } void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) { - assert(mp_obj_is_type(self_in, &mp_type_tuple)); + assert(mp_obj_is_tuple_compatible(self_in)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); *len = self->len; *items = &self->items[0]; From 1022f9cc35564b216a4bcd7c65e8243c810a0ca9 Mon Sep 17 00:00:00 2001 From: Tom McDermott Date: Mon, 5 Aug 2019 15:15:28 +1000 Subject: [PATCH 0392/1299] py/modstruct: Fix struct.unpack with unaligned offset of native type. With this patch alignment is done relative to the start of the buffer that is being unpacked, not the raw pointer value, as per CPython. Fixes issue #3314. --- extmod/moductypes.c | 2 +- py/binary.c | 6 +++--- py/binary.h | 2 +- py/modstruct.c | 3 ++- tests/basics/struct_endian.py | 17 +++++++++++++++++ 5 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 tests/basics/struct_endian.py diff --git a/extmod/moductypes.c b/extmod/moductypes.c index 9b46371f36f3e..d4c7611dfe502 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -299,7 +299,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, ucty static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) { char struct_type = big_endian ? '>' : '<'; static const char type2char[16] = "BbHhIiQq------fd"; - return mp_binary_get_val(struct_type, type2char[val_type], &p); + return mp_binary_get_val(struct_type, type2char[val_type], p, &p); } static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) { diff --git a/py/binary.c b/py/binary.c index a142776c37cb2..9810e46600bb4 100644 --- a/py/binary.c +++ b/py/binary.c @@ -185,14 +185,14 @@ long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, con } #define is_signed(typecode) (typecode > 'Z') -mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) { +mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr) { byte *p = *ptr; mp_uint_t align; size_t size = mp_binary_get_size(struct_type, val_type, &align); if (struct_type == '@') { - // Make pointer aligned - p = (byte*)MP_ALIGN(p, (size_t)align); + // Align p relative to p_base + p = p_base + (uintptr_t)MP_ALIGN(p - p_base, (size_t)align); #if MP_ENDIANNESS_LITTLE struct_type = '<'; #else diff --git a/py/binary.h b/py/binary.h index 71182042f908b..092b722886370 100644 --- a/py/binary.h +++ b/py/binary.h @@ -38,7 +38,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign); mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index); void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in); void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val); -mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr); +mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr); void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr); long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src); void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val); diff --git a/py/modstruct.c b/py/modstruct.c index 8617a8e0d3e0d..957e4917b6d95 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -146,6 +146,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { } p += offset; } + byte *p_base = p; // Check that the input buffer is big enough to unpack all the values if (p + total_sz > end_p) { @@ -164,7 +165,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { res->items[i++] = item; } else { while (cnt--) { - item = mp_binary_get_val(fmt_type, *fmt, &p); + item = mp_binary_get_val(fmt_type, *fmt, p_base, &p); res->items[i++] = item; } } diff --git a/tests/basics/struct_endian.py b/tests/basics/struct_endian.py new file mode 100644 index 0000000000000..ae32438245892 --- /dev/null +++ b/tests/basics/struct_endian.py @@ -0,0 +1,17 @@ +# test ustruct and endian specific things + +try: + import ustruct as struct +except: + try: + import struct + except ImportError: + print("SKIP") + raise SystemExit + +# unpack/unpack_from with unaligned native type +buf = b'0123456789' +print(struct.unpack('h', memoryview(buf)[1:3])) +print(struct.unpack_from('i', buf, 1)) +print(struct.unpack_from('@i', buf, 1)) +print(struct.unpack_from('@ii', buf, 1)) From 24c3e9b283da26093ca653fc6b441042fedec135 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 2 Sep 2019 12:57:51 +1000 Subject: [PATCH 0393/1299] py/modstruct: Fix struct.pack_into with unaligned offset of native type. Following the same fix for unpack. --- extmod/moductypes.c | 2 +- py/binary.c | 6 +++--- py/binary.h | 2 +- py/modstruct.c | 3 ++- tests/basics/struct_endian.py | 7 +++++++ 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/extmod/moductypes.c b/extmod/moductypes.c index d4c7611dfe502..cf83f43e33b93 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -305,7 +305,7 @@ static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) { static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) { char struct_type = big_endian ? '>' : '<'; static const char type2char[16] = "BbHhIiQq------fd"; - mp_binary_set_val(struct_type, type2char[val_type], val, &p); + mp_binary_set_val(struct_type, type2char[val_type], val, p, &p); } static inline mp_uint_t get_aligned_basic(uint val_type, void *p) { diff --git a/py/binary.c b/py/binary.c index 9810e46600bb4..dfd25018c1e90 100644 --- a/py/binary.c +++ b/py/binary.c @@ -250,14 +250,14 @@ void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t } } -void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) { +void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr) { byte *p = *ptr; mp_uint_t align; size_t size = mp_binary_get_size(struct_type, val_type, &align); if (struct_type == '@') { - // Make pointer aligned - p = (byte*)MP_ALIGN(p, (size_t)align); + // Align p relative to p_base + p = p_base + (uintptr_t)MP_ALIGN(p - p_base, (size_t)align); if (MP_ENDIANNESS_LITTLE) { struct_type = '<'; } else { diff --git a/py/binary.h b/py/binary.h index 092b722886370..ac24378d2c3d1 100644 --- a/py/binary.h +++ b/py/binary.h @@ -39,7 +39,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index); void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in); void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val); mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr); -void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr); +void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr); long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src); void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val); diff --git a/py/modstruct.c b/py/modstruct.c index 957e4917b6d95..3e7d90ec13448 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -180,6 +180,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, c const char *fmt = mp_obj_str_get_str(fmt_in); char fmt_type = get_fmt_type(&fmt); + byte *p_base = p; size_t i; for (i = 0; i < n_args;) { mp_uint_t cnt = 1; @@ -204,7 +205,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, c } else { // If we run out of args then we just finish; CPython would raise struct.error while (cnt-- && i < n_args) { - mp_binary_set_val(fmt_type, *fmt, args[i++], &p); + mp_binary_set_val(fmt_type, *fmt, args[i++], p_base, &p); } } fmt++; diff --git a/tests/basics/struct_endian.py b/tests/basics/struct_endian.py index ae32438245892..91f5539c15927 100644 --- a/tests/basics/struct_endian.py +++ b/tests/basics/struct_endian.py @@ -15,3 +15,10 @@ print(struct.unpack_from('i', buf, 1)) print(struct.unpack_from('@i', buf, 1)) print(struct.unpack_from('@ii', buf, 1)) + +# pack_into with unaligned native type +buf = bytearray(b'>----<<<<<<<') +struct.pack_into('i', buf, 1, 0x30313233) +print(buf) +struct.pack_into('@ii', buf, 3, 0x34353637, 0x41424344) +print(buf) From c348e791879e8615347403f541717eb9386fe4ee Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 2 Sep 2019 13:09:44 +1000 Subject: [PATCH 0394/1299] py/binary: Change mp_uint_t to size_t for index, size, align args. Reduces code size for nan-box builds, otherwise changes nothing. --- py/binary.c | 20 ++++++++++---------- py/binary.h | 12 ++++++------ py/modstruct.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/py/binary.c b/py/binary.c index dfd25018c1e90..83f28db91a007 100644 --- a/py/binary.c +++ b/py/binary.c @@ -42,7 +42,7 @@ #define alignof(type) offsetof(struct { char c; type t; }, t) #endif -size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { +size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { size_t size = 0; int align = 1; switch (struct_type) { @@ -113,7 +113,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { return size; } -mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) { +mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) { mp_int_t val = 0; switch (typecode) { case 'b': @@ -162,7 +162,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) { // The long long type is guaranteed to hold at least 64 bits, and size is at // most 8 (for q and Q), so we will always be able to parse the given data // and fit it into a long long. -long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src) { +long long mp_binary_get_int(size_t size, bool is_signed, bool big_endian, const byte *src) { int delta; if (!big_endian) { delta = -1; @@ -187,12 +187,12 @@ long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, con #define is_signed(typecode) (typecode > 'Z') mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr) { byte *p = *ptr; - mp_uint_t align; + size_t align; size_t size = mp_binary_get_size(struct_type, val_type, &align); if (struct_type == '@') { // Align p relative to p_base - p = p_base + (uintptr_t)MP_ALIGN(p - p_base, (size_t)align); + p = p_base + (uintptr_t)MP_ALIGN(p - p_base, align); #if MP_ENDIANNESS_LITTLE struct_type = '<'; #else @@ -231,7 +231,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte * } } -void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val) { +void mp_binary_set_int(size_t val_sz, bool big_endian, byte *dest, mp_uint_t val) { if (MP_ENDIANNESS_LITTLE && !big_endian) { memcpy(dest, &val, val_sz); } else if (MP_ENDIANNESS_BIG && big_endian) { @@ -252,12 +252,12 @@ void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr) { byte *p = *ptr; - mp_uint_t align; + size_t align; size_t size = mp_binary_get_size(struct_type, val_type, &align); if (struct_type == '@') { // Align p relative to p_base - p = p_base + (uintptr_t)MP_ALIGN(p - p_base, (size_t)align); + p = p_base + (uintptr_t)MP_ALIGN(p - p_base, align); if (MP_ENDIANNESS_LITTLE) { struct_type = '<'; } else { @@ -315,7 +315,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p mp_binary_set_int(MIN((size_t)size, sizeof(val)), struct_type == '>', p, val); } -void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in) { +void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_in) { switch (typecode) { #if MICROPY_PY_BUILTINS_FLOAT case 'f': @@ -342,7 +342,7 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v } } -void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val) { +void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_int_t val) { switch (typecode) { case 'b': ((signed char*)p)[index] = val; diff --git a/py/binary.h b/py/binary.h index ac24378d2c3d1..5c645bcaaa9c2 100644 --- a/py/binary.h +++ b/py/binary.h @@ -34,13 +34,13 @@ // type-specification errors due to end-of-string. #define BYTEARRAY_TYPECODE 1 -size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign); -mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index); -void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in); -void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val); +size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign); +mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index); +void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_in); +void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_int_t val); mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr); void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr); -long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src); -void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val); +long long mp_binary_get_int(size_t size, bool is_signed, bool big_endian, const byte *src); +void mp_binary_set_int(size_t val_sz, bool big_endian, byte *dest, mp_uint_t val); #endif // MICROPY_INCLUDED_PY_BINARY_H diff --git a/py/modstruct.c b/py/modstruct.c index 3e7d90ec13448..36af4260eef37 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -97,7 +97,7 @@ STATIC size_t calc_size_items(const char *fmt, size_t *total_sz) { size += cnt; } else { total_cnt += cnt; - mp_uint_t align; + size_t align; size_t sz = mp_binary_get_size(fmt_type, *fmt, &align); while (cnt--) { // Apply alignment From b29fae0c564bae271f3659563a2a61230dab5def Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 2 Sep 2019 13:30:16 +1000 Subject: [PATCH 0395/1299] py/bc: Fix size calculation of UNWIND_JUMP opcode in mp_opcode_format. Prior to this patch mp_opcode_format would calculate the incorrect size of the MP_BC_UNWIND_JUMP opcode, missing the additional byte. But, because opcodes below 0x10 are unused and treated as bytes in the .mpy load/save and freezing code, this bug did not show any symptoms, since nested unwind jumps would rarely (if ever) reach a depth of 16 (so the extra byte of this opcode would be between 0x01 and 0x0f and be correctly loaded/saved/frozen simply as an undefined opcode). This patch fixes this bug by correctly accounting for the additional byte. . --- py/bc.c | 6 ++- tests/basics/try_except_break.py | 73 ++++++++++++++++++++++++++++ tests/basics/try_except_break.py.exp | 3 ++ tools/mpy-tool.py | 4 +- 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 tests/basics/try_except_break.py create mode 100644 tests/basics/try_except_break.py.exp diff --git a/py/bc.c b/py/bc.c index 7d0b13bd748fe..5625da8cf35f0 100644 --- a/py/bc.c +++ b/py/bc.c @@ -292,7 +292,8 @@ continue2:; #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE // The following table encodes the number of bytes that a specific opcode -// takes up. There are 3 special opcodes that always have an extra byte: +// takes up. There are 4 special opcodes that always have an extra byte: +// MP_BC_UNWIND_JUMP // MP_BC_MAKE_CLOSURE // MP_BC_MAKE_CLOSURE_DEFARGS // MP_BC_RAISE_VARARGS @@ -402,7 +403,8 @@ uint mp_opcode_format(const byte *ip, size_t *opcode_size, bool count_var_uint) ip += 3; } else { int extra_byte = ( - *ip == MP_BC_RAISE_VARARGS + *ip == MP_BC_UNWIND_JUMP + || *ip == MP_BC_RAISE_VARARGS || *ip == MP_BC_MAKE_CLOSURE || *ip == MP_BC_MAKE_CLOSURE_DEFARGS ); diff --git a/tests/basics/try_except_break.py b/tests/basics/try_except_break.py new file mode 100644 index 0000000000000..a7683f2185a49 --- /dev/null +++ b/tests/basics/try_except_break.py @@ -0,0 +1,73 @@ +# test deep unwind via break from nested try-except (22 of them) +while True: + print(1) + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + try: + print(2) + break + print(3) + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass + except: + pass +print(4) diff --git a/tests/basics/try_except_break.py.exp b/tests/basics/try_except_break.py.exp new file mode 100644 index 0000000000000..e8a01cd985125 --- /dev/null +++ b/tests/basics/try_except_break.py.exp @@ -0,0 +1,3 @@ +1 +2 +4 diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 3d2a8fb7c6562..e5c8f09597a3d 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -109,6 +109,7 @@ def access(self, idx): MP_OPCODE_OFFSET = 3 # extra bytes: +MP_BC_UNWIND_JUMP = 0x46 MP_BC_MAKE_CLOSURE = 0x62 MP_BC_MAKE_CLOSURE_DEFARGS = 0x63 MP_BC_RAISE_VARARGS = 0x5c @@ -215,7 +216,8 @@ def mp_opcode_format(bytecode, ip, count_var_uint, opcode_format=make_opcode_for ip += 3 else: extra_byte = ( - opcode == MP_BC_RAISE_VARARGS + opcode == MP_BC_UNWIND_JUMP + or opcode == MP_BC_RAISE_VARARGS or opcode == MP_BC_MAKE_CLOSURE or opcode == MP_BC_MAKE_CLOSURE_DEFARGS ) From 50482cdc0c50c53f43953cf101e586c34f5588ad Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 3 Sep 2019 12:27:01 +1000 Subject: [PATCH 0396/1299] esp32/Makefile: Fix subst->patsubst in ESPIDF_BOOTLOADER_SUPPORT_O. --- ports/esp32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 06cb553f4d1a2..cf1b24bfc8afa 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -290,7 +290,7 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard. ################################################################################ # List of object files from the ESP32 IDF components -ESPIDF_BOOTLOADER_SUPPORT_O = $(subst .c,.o,\ +ESPIDF_BOOTLOADER_SUPPORT_O = $(patsubst %.c,%.o,\ $(filter-out $(ESPCOMP)/bootloader_support/src/bootloader_init.c,\ $(wildcard $(ESPCOMP)/bootloader_support/src/*.c))) From 74fe8414499c9a156dfcf348c091b3bcef4caac3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 3 Sep 2019 13:05:10 +1000 Subject: [PATCH 0397/1299] docs/library/pyb.DAC.rst: Correct frequency for triangle mode output. Also correct comments in related code. --- docs/library/pyb.DAC.rst | 6 +++--- ports/stm32/dac.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/library/pyb.DAC.rst b/docs/library/pyb.DAC.rst index c67603a710fc3..9a465b9ce25d8 100644 --- a/docs/library/pyb.DAC.rst +++ b/docs/library/pyb.DAC.rst @@ -93,9 +93,9 @@ Methods .. method:: DAC.triangle(freq) - Generate a triangle wave. The value on the DAC output changes at - the given frequency, and the frequency of the repeating triangle wave - itself is 2048 times smaller. + Generate a triangle wave. The value on the DAC output changes at the given + frequency and ramps through the full 12-bit range (up and down). Therefore + the frequency of the repeating triangle wave itself is 8192 times smaller. .. method:: DAC.write(value) diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index f3dcccb3da251..485829c59c5f6 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -373,15 +373,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_noise_obj, pyb_dac_noise); #if defined(TIM6) /// \method triangle(freq) /// Generate a triangle wave. The value on the DAC output changes at -/// the given frequency, and the frequence of the repeating triangle wave -/// itself is 256 (or 1024, need to check) times smaller. +/// the given frequency, and the frequency of the repeating triangle wave +/// itself is 8192 times smaller. STATIC mp_obj_t pyb_dac_triangle(mp_obj_t self_in, mp_obj_t freq) { pyb_dac_obj_t *self = MP_OBJ_TO_PTR(self_in); // set TIM6 to trigger the DAC at the given frequency TIM6_Config(mp_obj_get_int(freq)); - // Configure DAC in triangle mode with trigger via TIM6 + // Configure DAC in full-scale triangle mode with trigger via TIM6 uint32_t cr = DAC_TRIANGLEAMPLITUDE_4095 | DAC_CR_WAVE1_1 | DAC_TRIGGER_T6_TRGO; pyb_dac_reconfigure(self, cr, self->outbuf_waveform, 0); From 4beb6c21caaed38cee3278e3bbab437eccdb2169 Mon Sep 17 00:00:00 2001 From: stijn Date: Tue, 3 Sep 2019 10:08:03 +0200 Subject: [PATCH 0398/1299] windows/msvc: Treat compiler warnings as errors. This is consistent with the other ports and helps catching problems early. --- ports/windows/msvc/common.props | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/windows/msvc/common.props b/ports/windows/msvc/common.props index 26ea78e7e5111..5fe1b45fefb6a 100644 --- a/ports/windows/msvc/common.props +++ b/ports/windows/msvc/common.props @@ -18,6 +18,7 @@ false true false + true true From 8fc00928ea0ec2dd9ab88037105aaaf7dbf128c3 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 3 Sep 2019 16:08:37 +1000 Subject: [PATCH 0399/1299] stm32/dma: Fix DMA config for L0 MCUs. --- ports/stm32/dma.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 3d275684d2c32..734cf2e98006d 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -97,7 +97,7 @@ struct _dma_descr_t { static const DMA_InitTypeDef dma_init_struct_spi_i2c = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32H7) || defined(STM32L4) + #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) .Request = 0, #endif .Direction = 0, @@ -120,7 +120,7 @@ static const DMA_InitTypeDef dma_init_struct_spi_i2c = { static const DMA_InitTypeDef dma_init_struct_sdio = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32L4) + #elif defined(STM32L0) || defined(STM32L4) .Request = 0, #endif .Direction = 0, @@ -130,7 +130,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { .MemDataAlignment = DMA_MDATAALIGN_WORD, #if defined(STM32F4) || defined(STM32F7) .Mode = DMA_PFCTRL, - #elif defined(STM32L4) + #elif defined(STM32L0) || defined(STM32L4) .Mode = DMA_NORMAL, #endif .Priority = DMA_PRIORITY_VERY_HIGH, @@ -148,7 +148,7 @@ static const DMA_InitTypeDef dma_init_struct_sdio = { static const DMA_InitTypeDef dma_init_struct_dac = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32H7) || defined(STM32L4) + #elif defined(STM32H7) || defined(STM32L0) || defined(STM32L4) .Request = 0, #endif .Direction = 0, @@ -336,31 +336,31 @@ static const uint8_t dma_irqn[NSTREAM] = { // number. The duplicate streams are ok as long as they aren't used at the same time. // DMA1 streams -const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, DMA_REQUEST_1, dma_id_1, &dma_init_struct_spi_i2c }; -const dma_descr_t dma_I2C_3_TX = { DMA1_Channel2, DMA_REQUEST_3, dma_id_1, &dma_init_struct_spi_i2c }; -const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, DMA_REQUEST_1, dma_id_2, &dma_init_struct_spi_i2c }; -const dma_descr_t dma_I2C_3_RX = { DMA1_Channel3, DMA_REQUEST_3, dma_id_2, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, DMA_REQUEST_1, dma_id_1, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_3_TX = { DMA1_Channel2, DMA_REQUEST_14, dma_id_1, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_DAC -const dma_descr_t dma_DAC_1_TX = { DMA1_Channel3, DMA_REQUEST_6, dma_id_2, &dma_init_struct_dac }; +const dma_descr_t dma_DAC_1_TX = { DMA1_Channel2, DMA_REQUEST_9, dma_id_1, &dma_init_struct_dac }; #endif -const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, DMA_REQUEST_1, dma_id_3, &dma_init_struct_spi_i2c }; -const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, DMA_REQUEST_3, dma_id_3, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, DMA_REQUEST_1, dma_id_2, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_3_RX = { DMA1_Channel3, DMA_REQUEST_14, dma_id_2, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, DMA_REQUEST_2, dma_id_3, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, DMA_REQUEST_7, dma_id_3, &dma_init_struct_spi_i2c }; #if MICROPY_HW_ENABLE_DAC -const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_5, dma_id_3, &dma_init_struct_dac }; +const dma_descr_t dma_DAC_2_TX = { DMA1_Channel4, DMA_REQUEST_15, dma_id_3, &dma_init_struct_dac }; #endif -const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_1, dma_id_4, &dma_init_struct_spi_i2c }; -const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, DMA_REQUEST_3, dma_id_4, &dma_init_struct_spi_i2c }; -const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_3, dma_id_5, &dma_init_struct_spi_i2c }; -const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_3, dma_id_6, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, DMA_REQUEST_2, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, DMA_REQUEST_7, dma_id_4, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, DMA_REQUEST_6, dma_id_5, &dma_init_struct_spi_i2c }; +const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, DMA_REQUEST_6, dma_id_6, &dma_init_struct_spi_i2c }; static const uint8_t dma_irqn[NSTREAM] = { DMA1_Channel1_IRQn, DMA1_Channel2_3_IRQn, + DMA1_Channel2_3_IRQn, + DMA1_Channel4_5_6_7_IRQn, + DMA1_Channel4_5_6_7_IRQn, + DMA1_Channel4_5_6_7_IRQn, DMA1_Channel4_5_6_7_IRQn, - 0, - 0, - 0, - 0, }; #elif defined(STM32L4) @@ -724,10 +724,10 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir dma_enable_clock(dma_id); - #if defined(STM32H7) || defined(STM32L4) - // Always reset and configure the H7 and L4 DMA peripheral + #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) + // Always reset and configure the H7 and L0/L4 DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) - // TODO: understand how L4 DMA works so this is not needed + // TODO: understand how L0/L4 DMA works so this is not needed HAL_DMA_DeInit(dma); HAL_DMA_Init(dma); NVIC_SetPriority(IRQn_NONNEG(dma_irqn[dma_id]), IRQ_PRI_DMA); From 06661890de479ac1846772567f341f0707b339a7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 4 Sep 2019 10:17:32 +1000 Subject: [PATCH 0400/1299] stm32/powerctrl: Fix machine.bootloader() for L0 MCUs. --- ports/stm32/powerctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 68a8bfdaf340a..dfd9e8262d940 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -76,7 +76,7 @@ void powerctrl_check_enter_bootloader(void) { if ((bl_addr & 0xfff) == 0 && (RCC->RCC_SR & RCC_SR_SFTRSTF)) { // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader RCC->RCC_SR = RCC_SR_RMVF; - #if defined(STM32F0) || defined(STM32F4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32F0) || defined(STM32F4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); #endif uint32_t r0 = BL_STATE[0]; From 8a237237a3889036e1a612237b0e585fa0713a66 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 4 Sep 2019 15:05:03 +1000 Subject: [PATCH 0401/1299] docs: Rename machine.ADC docs to machine.ADCWiPy. To signify that this ADC documentation is specific to the WiPy, and to make way for a standardised ADC documentation. --- docs/library/index.rst | 1 + .../{machine.ADC.rst => machine.ADCWiPy.rst} | 21 ++++++++++++------- docs/wipy/quickref.rst | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) rename docs/library/{machine.ADC.rst => machine.ADCWiPy.rst} (77%) diff --git a/docs/library/index.rst b/docs/library/index.rst index b464e85fa2f73..4e23e6e01da84 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -136,6 +136,7 @@ The following libraries and classes are specific to the WiPy. :maxdepth: 2 wipy.rst + machine.ADCWiPy.rst machine.TimerWiPy.rst diff --git a/docs/library/machine.ADC.rst b/docs/library/machine.ADCWiPy.rst similarity index 77% rename from docs/library/machine.ADC.rst rename to docs/library/machine.ADCWiPy.rst index 4c7a04d74f07f..4a4f0524c8f0b 100644 --- a/docs/library/machine.ADC.rst +++ b/docs/library/machine.ADCWiPy.rst @@ -1,8 +1,15 @@ .. currentmodule:: machine -.. _machine.ADC: +.. _machine.ADCWiPy: -class ADC -- analog to digital conversion -========================================= +class ADCWiPy -- analog to digital conversion +============================================= + +.. note:: + + This class is a non-standard ADC implementation for the WiPy. + It is available simply as ``machine.ADC`` on the WiPy but is named in the + documentation below as ``machine.ADCWiPy`` to distinguish it from the + more general :ref:`machine.ADC ` class. Usage:: @@ -15,7 +22,7 @@ Usage:: Constructors ------------ -.. class:: ADC(id=0, \*, bits=12) +.. class:: ADCWiPy(id=0, \*, bits=12) Create an ADC object associated with the given pin. This allows you to then read analog values on that pin. @@ -32,7 +39,7 @@ Constructors Methods ------- -.. method:: ADC.channel(id, \*, pin) +.. method:: ADCWiPy.channel(id, \*, pin) Create an analog pin. If only channel ID is given, the correct pin will be selected. Alternatively, only the pin can be passed and the correct @@ -43,11 +50,11 @@ Methods apin = adc.channel(pin='GP3') apin = adc.channel(id=1, pin='GP3') -.. method:: ADC.init() +.. method:: ADCWiPy.init() Enable the ADC block. -.. method:: ADC.deinit() +.. method:: ADCWiPy.deinit() Disable the ADC block. diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst index 7aa832fd2529b..6349676cf7e1d 100644 --- a/docs/wipy/quickref.rst +++ b/docs/wipy/quickref.rst @@ -82,7 +82,7 @@ See :ref:`machine.Pin ` and :ref:`machine.Timer `. : ADC (analog to digital conversion) ---------------------------------- -See :ref:`machine.ADC `. :: +See :ref:`machine.ADCWiPy `. :: from machine import ADC From e509da22df8cd337c1cc8dd531c6150e6fdb4ee0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 4 Sep 2019 15:33:40 +1000 Subject: [PATCH 0402/1299] docs/library: Specify new machine.ADC class. This initial specification is only for the ADC constructor and read_u16() method. --- docs/library/machine.ADC.rst | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/library/machine.ADC.rst diff --git a/docs/library/machine.ADC.rst b/docs/library/machine.ADC.rst new file mode 100644 index 0000000000000..1404b454ae7f5 --- /dev/null +++ b/docs/library/machine.ADC.rst @@ -0,0 +1,35 @@ +.. currentmodule:: machine +.. _machine.ADC: + +class ADC -- analog to digital conversion +========================================= + +The ADC class provides an interface to analog-to-digital convertors, and +represents a single endpoint that can sample a continuous voltage and +convert it to a discretised value. + +Example usage:: + + import machine + + adc = machine.ADC(pin) # create an ADC object acting on a pin + val = adc.read_u16() # read a raw analog value in the range 0-65535 + +Constructors +------------ + +.. class:: ADC(id) + + Access the ADC associated with a source identified by *id*. This + *id* may be an integer (usually specifying a channel number), a + :ref:`Pin ` object, or other value supported by the + underlying machine. + +Methods +------- + +.. method:: ADC.read_u16() + + Take an analog reading and return an integer in the range 0-65535. + The return value represents the raw reading taken by the ADC, scaled + such that the minimum value is 0 and the maximum value is 65535. From ebacdfabb6e2ac695d6660f2a6420ab84db76d39 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 20 Jul 2019 12:37:58 +1000 Subject: [PATCH 0403/1299] stm32/machine_adc: Add machine.ADC class. --- ports/stm32/Makefile | 1 + ports/stm32/machine_adc.c | 409 ++++++++++++++++++++++++++++++++++++++ ports/stm32/modmachine.c | 4 +- ports/stm32/modmachine.h | 2 + 4 files changed, 413 insertions(+), 3 deletions(-) create mode 100644 ports/stm32/machine_adc.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index e868d6de1bc75..6c0c29572e8ab 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -261,6 +261,7 @@ SRC_C = \ eth.c \ gccollect.c \ help.c \ + machine_adc.c \ machine_i2c.c \ machine_spi.c \ machine_uart.c \ diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c new file mode 100644 index 0000000000000..58c0133595545 --- /dev/null +++ b/ports/stm32/machine_adc.c @@ -0,0 +1,409 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" + +#if defined(STM32F0) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) +#define ADC_V2 (1) +#else +#define ADC_V2 (0) +#endif + +#if defined(STM32F0) || defined(STM32L0) +#define ADC_STAB_DELAY_US (1) +#define ADC_TEMPSENSOR_DELAY_US (10) +#elif defined(STM32L4) +#define ADC_STAB_DELAY_US (10) +#elif defined(STM32WB) +#define ADC_STAB_DELAY_US (1) +#endif + +#if defined(STM32F0) +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_71CYCLES_5 +#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_239CYCLES_5 +#elif defined(STM32F4) || defined(STM32F7) +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_15CYCLES +#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_480CYCLES +#elif defined(STM32H7) +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_8CYCLES_5 +#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_387CYCLES_5 +#elif defined(STM32L0) +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 +#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5 +#elif defined(STM32L4) || defined(STM32WB) +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 +#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5 +#endif + +// Timeout for waiting for end-of-conversion +#define ADC_EOC_TIMEOUT_MS (10) + +// This is a synthesised channel representing the maximum ADC reading (useful to scale other channels) +#define ADC_CHANNEL_VREF (0xffff) + +static inline void adc_stabilisation_delay_us(uint32_t us) { + mp_hal_delay_us(us + 1); +} + +STATIC void adc_wait_eoc(ADC_TypeDef *adc, int32_t timeout_ms) { + uint32_t t0 = mp_hal_ticks_ms(); + #if ADC_V2 + while (!(adc->ISR & ADC_FLAG_EOC)) + #else + while (!(adc->SR & ADC_FLAG_EOC)) + #endif + { + if (mp_hal_ticks_ms() - t0 > timeout_ms) { + break; // timeout + } + } +} + +#if defined(STM32H7) +STATIC const uint8_t adc_cr_to_bits_table[] = {16, 14, 12, 10, 8, 8, 8, 8}; +#else +STATIC const uint8_t adc_cr_to_bits_table[] = {12, 10, 8, 6}; +#endif + +STATIC void adc_config(ADC_TypeDef *adc, uint32_t bits) { + #if defined(STM32L4) || defined(STM32WB) + __HAL_RCC_ADC_CLK_ENABLE(); + #else + if (adc == ADC1) { + #if defined(STM32H7) + __HAL_RCC_ADC12_CLK_ENABLE(); + #else + __HAL_RCC_ADC1_CLK_ENABLE(); + #endif + } + #if defined(ADC2) + if (adc == ADC2) { + #if defined(STM32H7) + __HAL_RCC_ADC12_CLK_ENABLE(); + #else + __HAL_RCC_ADC2_CLK_ENABLE(); + #endif + } + #endif + #if defined(ADC3) + if (adc == ADC3) { + __HAL_RCC_ADC3_CLK_ENABLE(); + } + #endif + #endif + + #if ADC_V2 + if (adc->CR & ADC_CR_ADEN) { + // ADC enabled, need to disable it to change configuration + if (adc->CR & ADC_CR_ADSTART) { + adc->CR |= ADC_CR_ADSTP; + while (adc->CR & ADC_CR_ADSTP) { + } + } + adc->CR |= ADC_CR_ADDIS; + while (adc->CR & ADC_CR_ADDIS) { + } + } + #endif + + // TODO check all these + #if defined(STM32F0) + adc->CFGR2 = 1 << ADC_CFGR2_CKMODE_Pos; // PCLK/2 (synchronous clock mode) + #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L4) + ADC123_COMMON->CCR = 0; // ADCPR=PCLK/2 + #elif defined(STM32H7) + __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); + #elif defined(STM32L0) || defined(STM32WB) + ADC1_COMMON->CCR = 0; // ADCPR=PCLK/2 + #endif + + // Find resolution, defaulting to last element in table + uint32_t res; + for (res = 0; res <= MP_ARRAY_SIZE(adc_cr_to_bits_table); ++res) { + if (adc_cr_to_bits_table[res] == bits) { + break; + } + } + + #if defined(STM32F0) || defined(STM32L0) + + uint32_t cfgr1_clr = ADC_CFGR1_CONT | ADC_CFGR1_EXTEN | ADC_CFGR1_ALIGN | ADC_CFGR1_RES | ADC_CFGR1_DMAEN; + uint32_t cfgr1 = res << ADC_CFGR1_RES_Pos; + adc->CFGR1 = (adc->CFGR1 & ~cfgr1_clr) | cfgr1; + + #elif defined(STM32F4) || defined(STM32F7) + + uint32_t cr1_clr = ADC_CR1_RES; + uint32_t cr1 = res << ADC_CR1_RES_Pos; + adc->CR1 = (adc->CR1 & ~cr1_clr) | cr1; + uint32_t cr2_clr = ADC_CR2_EXTEN | ADC_CR2_ALIGN | ADC_CR2_DMA | ADC_CR2_CONT; + uint32_t cr2 = 0; + adc->CR2 = (adc->CR2 & ~cr2_clr) | cr2; + adc->SQR1 = 1 << ADC_SQR1_L_Pos; // 1 conversion in regular sequence + + #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + + uint32_t cfgr_clr = ADC_CFGR_CONT | ADC_CFGR_EXTEN | ADC_CFGR_RES; + #if defined(STM32H7) + cfgr_clr |= ADC_CFGR_DMNGT; + #else + cfgr_clr |= ADC_CFGR_ALIGN | ADC_CFGR_DMAEN; + #endif + uint32_t cfgr = res << ADC_CFGR_RES_Pos; + adc->CFGR = (adc->CFGR & ~cfgr_clr) | cfgr; + + #endif +} + +STATIC int adc_get_bits(ADC_TypeDef *adc) { + #if defined(STM32F0) || defined(STM32L0) + uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos; + #elif defined(STM32F4) || defined(STM32F7) + uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos; + #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + uint32_t res = (adc->CFGR & ADC_CFGR_RES) >> ADC_CFGR_RES_Pos; + #endif + return adc_cr_to_bits_table[res]; +} + +STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t sample_time) { + #if ADC_V2 + if (!(adc->CR & ADC_CR_ADEN)) { + if (adc->CR) { + // Cannot enable ADC with CR!=0 + return; + } + adc->CR |= ADC_CR_ADEN; + adc_stabilisation_delay_us(ADC_STAB_DELAY_US); + while (!(adc->ISR & ADC_ISR_ADRDY)) { + } + } + #else + if (!(adc->CR2 & ADC_CR2_ADON)) { + adc->CR2 |= ADC_CR2_ADON; + adc_stabilisation_delay_us(ADC_STAB_DELAY_US); + } + #endif + + #if defined(STM32F0) || defined(STM32L0) + + if (channel == ADC_CHANNEL_VREFINT) { + ADC1_COMMON->CCR |= ADC_CCR_VREFEN; + } else if (channel == ADC_CHANNEL_TEMPSENSOR) { + ADC1_COMMON->CCR |= ADC_CCR_TSEN; + adc_stabilisation_delay_us(ADC_TEMPSENSOR_DELAY_US); + #if defined(ADC_CHANNEL_VBAT) + } else if (channel == ADC_CHANNEL_VBAT) { + ADC1_COMMON->CCR |= ADC_CCR_VBATEN; + #endif + } + adc->SMPR = sample_time << ADC_SMPR_SMP_Pos; // select sample time + adc->CHSELR = 1 << channel; // select channel for conversion + + #elif defined(STM32F4) || defined(STM32F7) + + if (channel == ADC_CHANNEL_VREFINT || channel == ADC_CHANNEL_TEMPSENSOR) { + ADC123_COMMON->CCR = (ADC123_COMMON->CCR & ~ADC_CCR_VBATE) | ADC_CCR_TSVREFE; + if (channel == ADC_CHANNEL_TEMPSENSOR) { + adc_stabilisation_delay_us(ADC_TEMPSENSOR_DELAY_US); + } + } else if (channel == ADC_CHANNEL_VBAT) { + ADC123_COMMON->CCR |= ADC_CCR_VBATE; + } + + adc->SQR3 = (channel & 0x1f) << ADC_SQR3_SQ1_Pos; // select channel for first conversion + + __IO uint32_t *smpr; + if (channel <= 9) { + smpr = &adc->SMPR2; + } else { + smpr = &adc->SMPR1; + channel -= 10; + } + *smpr = (*smpr & ~(7 << (channel * 3))) | sample_time << (channel * 3); // select sample time + + #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + + #if defined(STM32H7) + ADC_Common_TypeDef *adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON; + #elif defined(STM32L4) + ADC_Common_TypeDef *adc_common = ADC123_COMMON; + #elif defined(STM32WB) + ADC_Common_TypeDef *adc_common = ADC1_COMMON; + #endif + if (channel == ADC_CHANNEL_VREFINT) { + adc_common->CCR |= ADC_CCR_VREFEN; + } else if (channel == ADC_CHANNEL_TEMPSENSOR) { + adc_common->CCR |= ADC_CCR_TSEN; + adc_stabilisation_delay_us(ADC_TEMPSENSOR_DELAY_US); + } else if (channel == ADC_CHANNEL_VBAT) { + adc_common->CCR |= ADC_CCR_VBATEN; + } + adc->SQR1 = (channel & 0x1f) << ADC_SQR1_SQ1_Pos | 1 << ADC_SQR1_L_Pos; + __IO uint32_t *smpr; + if (channel <= 9) { + smpr = &adc->SMPR1; + } else { + smpr = &adc->SMPR2; + channel -= 10; + } + *smpr = (*smpr & ~(7 << (channel * 3))) | sample_time << (channel * 3); // select sample time + + #endif +} + +STATIC uint32_t adc_read_channel(ADC_TypeDef *adc) { + #if ADC_V2 + adc->CR |= ADC_CR_ADSTART; + #else + adc->CR2 |= ADC_CR2_SWSTART; + #endif + adc_wait_eoc(adc, ADC_EOC_TIMEOUT_MS); + uint32_t value = adc->DR; + return value; +} + +STATIC uint32_t adc_config_and_read_u16(ADC_TypeDef *adc, uint32_t channel, uint32_t sample_time) { + if (channel == ADC_CHANNEL_VREF) { + return 0xffff; + } + + adc_config_channel(adc, channel, sample_time); + uint32_t raw = adc_read_channel(adc); + uint32_t bits = adc_get_bits(adc); + // Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16) + #if defined(STM32H7) + if (bits < 8) { + // For 6 and 7 bits + return raw << (16 - bits) | raw << (16 - 2 * bits) | raw >> (3 * bits - 16); + } + #endif + return raw << (16 - bits) | raw >> (2 * bits - 16); +} + +/******************************************************************************/ +// MicroPython bindings for machine.ADC + +const mp_obj_type_t machine_adc_type; + +typedef struct _machine_adc_obj_t { + mp_obj_base_t base; + ADC_TypeDef *adc; + uint32_t channel; + uint32_t sample_time; +} machine_adc_obj_t; + +STATIC void machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + #if defined(STM32F0) || defined(STM32L0) || defined(STM32WB) + unsigned adc_id = 1; + #else + unsigned adc_id = (self->adc - ADC1) / (ADC2 - ADC1) + 1; + #endif + mp_printf(print, "", adc_id, self->channel); +} + +// ADC(id) +STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // Check number of arguments + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + mp_obj_t source = all_args[0]; + + uint32_t channel; + uint32_t sample_time = ADC_SAMPLETIME_DEFAULT; + ADC_TypeDef *adc; + if (mp_obj_is_int(source)) { + adc = ADC1; + channel = mp_obj_get_int(source); + if (channel == ADC_CHANNEL_VREFINT + || channel == ADC_CHANNEL_TEMPSENSOR + #if defined(ADC_CHANNEL_VBAT) + || channel == ADC_CHANNEL_VBAT + #endif + ) { + sample_time = ADC_SAMPLETIME_DEFAULT_INT; + } + } else { + const pin_obj_t *pin = pin_find(source); + if (pin->adc_num & PIN_ADC1) { + adc = ADC1; + #if defined(ADC2) + } else if (pin->adc_num & PIN_ADC2) { + adc = ADC2; + #endif + #if defined(ADC2) + } else if (pin->adc_num & PIN_ADC3) { + adc = ADC3; + #endif + } else { + // No ADC function on given pin + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Pin(%q) does not have ADC capabilities", pin->name)); + } + channel = pin->adc_channel; + + // Configure the GPIO pin in ADC mode + mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); + } + + adc_config(adc, 12); + + machine_adc_obj_t *o = m_new_obj(machine_adc_obj_t); + o->base.type = &machine_adc_type; + o->adc = adc; + o->channel = channel; + o->sample_time = sample_time; + + return MP_OBJ_FROM_PTR(o); +} + +// read_u16() +STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(adc_config_and_read_u16(self->adc, self->channel, self->sample_time)); +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16); + +STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) }, + + { MP_ROM_QSTR(MP_QSTR_VREF), MP_ROM_INT(ADC_CHANNEL_VREF) }, + { MP_ROM_QSTR(MP_QSTR_CORE_VREF), MP_ROM_INT(ADC_CHANNEL_VREFINT) }, + { MP_ROM_QSTR(MP_QSTR_CORE_TEMP), MP_ROM_INT(ADC_CHANNEL_TEMPSENSOR) }, + #if defined(ADC_CHANNEL_VBAT) + { MP_ROM_QSTR(MP_QSTR_CORE_VBAT), MP_ROM_INT(ADC_CHANNEL_VBAT) }, + #endif +}; +STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); + +const mp_obj_type_t machine_adc_type = { + { &mp_type_type }, + .name = MP_QSTR_ADC, + .print = machine_adc_print, + .make_new = machine_adc_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict, +}; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index e45f81479bfb5..eaa536a1db802 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -392,9 +392,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) }, -#if 0 - { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, -#endif + { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #if MICROPY_PY_MACHINE_I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, #endif diff --git a/ports/stm32/modmachine.h b/ports/stm32/modmachine.h index 414e5b37c7a60..4b727d3cb9d8a 100644 --- a/ports/stm32/modmachine.h +++ b/ports/stm32/modmachine.h @@ -28,6 +28,8 @@ #include "py/obj.h" +extern const mp_obj_type_t machine_adc_type; + void machine_init(void); void machine_deinit(void); From 625609a7378ab6ee92855e031335cc1a915a99c8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 20 Jul 2019 12:41:20 +1000 Subject: [PATCH 0404/1299] esp8266/machine_adc: Rename pyb_adc_* to machine_adc_*. --- ports/esp8266/machine_adc.c | 34 +++++++++++++++++----------------- ports/esp8266/modmachine.c | 2 +- ports/esp8266/modmachine.h | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c index b422f0f9ecea2..13fbd53056e9d 100644 --- a/ports/esp8266/machine_adc.c +++ b/ports/esp8266/machine_adc.c @@ -30,17 +30,17 @@ #include "py/runtime.h" #include "user_interface.h" -const mp_obj_type_t pyb_adc_type; +const mp_obj_type_t machine_adc_type; -typedef struct _pyb_adc_obj_t { +typedef struct _machine_adc_obj_t { mp_obj_base_t base; bool isvdd; -} pyb_adc_obj_t; +} machine_adc_obj_t; -STATIC pyb_adc_obj_t pyb_adc_vdd3 = {{&pyb_adc_type}, true}; -STATIC pyb_adc_obj_t pyb_adc_adc = {{&pyb_adc_type}, false}; +STATIC machine_adc_obj_t machine_adc_vdd3 = {{&machine_adc_type}, true}; +STATIC machine_adc_obj_t machine_adc_adc = {{&machine_adc_type}, false}; -STATIC mp_obj_t pyb_adc_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, +STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); @@ -48,17 +48,17 @@ STATIC mp_obj_t pyb_adc_make_new(const mp_obj_type_t *type_in, size_t n_args, si switch (chn) { case 0: - return &pyb_adc_adc; + return &machine_adc_adc; case 1: - return &pyb_adc_vdd3; + return &machine_adc_vdd3; default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "not a valid ADC Channel: %d", chn)); } } -STATIC mp_obj_t pyb_adc_read(mp_obj_t self_in) { - pyb_adc_obj_t *adc = self_in; +STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) { + machine_adc_obj_t *adc = self_in; if (adc->isvdd) { return mp_obj_new_int(system_get_vdd33()); @@ -66,16 +66,16 @@ STATIC mp_obj_t pyb_adc_read(mp_obj_t self_in) { return mp_obj_new_int(system_adc_read()); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_adc_read_obj, pyb_adc_read); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read); -STATIC const mp_rom_map_elem_t pyb_adc_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_adc_read_obj) } +STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) } }; -STATIC MP_DEFINE_CONST_DICT(pyb_adc_locals_dict, pyb_adc_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); -const mp_obj_type_t pyb_adc_type = { +const mp_obj_type_t machine_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, - .make_new = pyb_adc_make_new, - .locals_dict = (mp_obj_dict_t*)&pyb_adc_locals_dict, + .make_new = machine_adc_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict, }; diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c index e20e8cb75710e..35d4918bd34ec 100644 --- a/ports/esp8266/modmachine.c +++ b/ports/esp8266/modmachine.c @@ -410,7 +410,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) }, - { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, + { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, #if MICROPY_PY_MACHINE_I2C { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, diff --git a/ports/esp8266/modmachine.h b/ports/esp8266/modmachine.h index eae351f68d3bf..cea382d24bdcf 100644 --- a/ports/esp8266/modmachine.h +++ b/ports/esp8266/modmachine.h @@ -5,7 +5,7 @@ extern const mp_obj_type_t pyb_pin_type; extern const mp_obj_type_t pyb_pwm_type; -extern const mp_obj_type_t pyb_adc_type; +extern const mp_obj_type_t machine_adc_type; extern const mp_obj_type_t pyb_rtc_type; extern const mp_obj_type_t pyb_uart_type; extern const mp_obj_type_t pyb_i2c_type; From 0e72cc90291d254014edee7be66b066c73d1fc71 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 20 Jul 2019 12:42:08 +1000 Subject: [PATCH 0405/1299] esp8266/machine_adc: Add read_u16 method and refactor. --- ports/esp8266/machine_adc.c | 43 ++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c index 13fbd53056e9d..932e5782f4aba 100644 --- a/ports/esp8266/machine_adc.c +++ b/ports/esp8266/machine_adc.c @@ -28,20 +28,32 @@ #include #include "py/runtime.h" +#include "py/mphal.h" #include "user_interface.h" -const mp_obj_type_t machine_adc_type; - typedef struct _machine_adc_obj_t { mp_obj_base_t base; bool isvdd; } machine_adc_obj_t; +extern const mp_obj_type_t machine_adc_type; + STATIC machine_adc_obj_t machine_adc_vdd3 = {{&machine_adc_type}, true}; STATIC machine_adc_obj_t machine_adc_adc = {{&machine_adc_type}, false}; -STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, - const mp_obj_t *args) { +STATIC uint16_t adc_read(machine_adc_obj_t *self) { + if (self->isvdd) { + return system_get_vdd33(); + } else { + return system_adc_read(); + } +} +void machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "ADC(%u)", self->isvdd); +} + +mp_obj_t machine_adc_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_int_t chn = mp_obj_get_int(args[0]); @@ -52,23 +64,27 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type_in, size_t n_args case 1: return &machine_adc_vdd3; default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - "not a valid ADC Channel: %d", chn)); + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ADC(%d) doesn't exist", chn)); } } -STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) { - machine_adc_obj_t *adc = self_in; +// read_u16() +STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint32_t value = adc_read(self); + return MP_OBJ_NEW_SMALL_INT(value * 65535 / 1024); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16); - if (adc->isvdd) { - return mp_obj_new_int(system_get_vdd33()); - } else { - return mp_obj_new_int(system_adc_read()); - } +// Legacy method +STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) { + machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(adc_read(self)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read); STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) } }; STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table); @@ -76,6 +92,7 @@ STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_tab const mp_obj_type_t machine_adc_type = { { &mp_type_type }, .name = MP_QSTR_ADC, + .print = machine_adc_print, .make_new = machine_adc_make_new, .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict, }; From 983283a8cd504e2f9438a836effa9e862f19ec97 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 20 Jul 2019 12:42:35 +1000 Subject: [PATCH 0406/1299] esp32/machine_adc: Add ADC.read_u16() method. --- ports/esp32/machine_adc.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c index d62f362e96b34..63e40448b4ab3 100644 --- a/ports/esp32/machine_adc.c +++ b/ports/esp32/machine_adc.c @@ -53,12 +53,15 @@ STATIC const madc_obj_t madc_obj[] = { {{&machine_adc_type}, GPIO_NUM_35, ADC1_CHANNEL_7}, }; +STATIC uint8_t adc_bit_width; + STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { static int initialized = 0; if (!initialized) { adc1_config_width(ADC_WIDTH_12Bit); + adc_bit_width = 12; initialized = 1; } @@ -79,6 +82,17 @@ STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ mp_printf(print, "ADC(Pin(%u))", self->gpio_id); } +// read_u16() +STATIC mp_obj_t madc_read_u16(mp_obj_t self_in) { + madc_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint32_t raw = adc1_get_raw(self->adc1_id); + // Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16) + uint32_t u16 = raw << (16 - adc_bit_width) | raw >> (2 * adc_bit_width - 16); + return MP_OBJ_NEW_SMALL_INT(u16); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(madc_read_u16_obj, madc_read_u16); + +// Legacy method STATIC mp_obj_t madc_read(mp_obj_t self_in) { madc_obj_t *self = self_in; int val = adc1_get_raw(self->adc1_id); @@ -99,13 +113,24 @@ MP_DEFINE_CONST_FUN_OBJ_2(madc_atten_obj, madc_atten); STATIC mp_obj_t madc_width(mp_obj_t cls_in, mp_obj_t width_in) { adc_bits_width_t width = mp_obj_get_int(width_in); esp_err_t err = adc1_config_width(width); - if (err == ESP_OK) return mp_const_none; - mp_raise_ValueError("Parameter Error"); + if (err != ESP_OK) { + mp_raise_ValueError("Parameter Error"); + } + switch (width) { + case ADC_WIDTH_9Bit: adc_bit_width = 9; break; + case ADC_WIDTH_10Bit: adc_bit_width = 10; break; + case ADC_WIDTH_11Bit: adc_bit_width = 11; break; + case ADC_WIDTH_12Bit: adc_bit_width = 12; break; + default: break; + } + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(madc_width_fun_obj, madc_width); MP_DEFINE_CONST_CLASSMETHOD_OBJ(madc_width_obj, MP_ROM_PTR(&madc_width_fun_obj)); STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&madc_read_u16_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&madc_read_obj) }, { MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&madc_atten_obj) }, { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&madc_width_obj) }, From 9cad134a2f861a0f8864b70ab80c9d6cc61c2932 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 25 Jul 2019 18:22:54 +1000 Subject: [PATCH 0407/1299] nrf/machine/adc: Add ADC.read_u16() method. --- ports/nrf/modules/machine/adc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ports/nrf/modules/machine/adc.c b/ports/nrf/modules/machine/adc.c index 55b68c6b80b69..b543c94f3968c 100644 --- a/ports/nrf/modules/machine/adc.c +++ b/ports/nrf/modules/machine/adc.c @@ -169,6 +169,20 @@ int16_t machine_adc_value_read(machine_adc_obj_t * adc_obj) { return value; } +// read_u16() +STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) { + machine_adc_obj_t *self = self_in; + int16_t raw = machine_adc_value_read(self); + #if defined(NRF52_SERIES) + // raw is signed but the channel is in single-ended mode and this method cannot return negative values + if (raw < 0) { + raw = 0; + } + #endif + // raw is an 8-bit value + return MP_OBJ_NEW_SMALL_INT(raw << 8 | raw); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_adc_read_u16_obj, machine_adc_read_u16); /// \method value() /// Read adc level. @@ -263,6 +277,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_machine_adc_battery_level_obj, machine_adc_b STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = { // instance methods + { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&mp_machine_adc_read_u16_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&mp_machine_adc_value_obj) }, // class methods From b766a6971eaa377ceb7d5a308b0cd4219e313ad3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 5 Sep 2019 19:19:01 +1000 Subject: [PATCH 0408/1299] nrf: Add ADC channel mapping to alt function table. --- ports/nrf/nrf52_af.csv | 16 ++++++++-------- ports/nrf/pin_defs_nrf5.h | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ports/nrf/nrf52_af.csv b/ports/nrf/nrf52_af.csv index 59686ff901037..bcb05c227f21e 100644 --- a/ports/nrf/nrf52_af.csv +++ b/ports/nrf/nrf52_af.csv @@ -1,9 +1,9 @@ P0,P0 P1,P1 -P2,P2 -P3,P3 -P4,P4 -P5,P5 +P2,P2,ADC1_CH0 +P3,P3,ADC1_CH1 +P4,P4,ADC1_CH2 +P5,P5,ADC1_CH3 P6,P6 P7,P7 P8,P8 @@ -26,10 +26,10 @@ P24,P24 P25,P25 P26,P26 P27,P27 -P28,P28 -P29,P29 -P30,P30 -P31,P31 +P28,P28,ADC1_CH4 +P29,P29,ADC1_CH5 +P30,P30,ADC1_CH6 +P31,P31,ADC1_CH7 P32,P32 P33,P33 P34,P34 diff --git a/ports/nrf/pin_defs_nrf5.h b/ports/nrf/pin_defs_nrf5.h index 99020ded7531f..db05aef995059 100644 --- a/ports/nrf/pin_defs_nrf5.h +++ b/ports/nrf/pin_defs_nrf5.h @@ -57,5 +57,8 @@ enum { // NRF_SPI_Type *SPIM; // NRF_SPIS_Type *SPIS; +enum { + PIN_ADC1 = (1 << 0), +}; typedef NRF_GPIO_Type pin_gpio_t; From c7fb93b844f474ff9a063c55f81f6e324a180da1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 5 Sep 2019 19:19:44 +1000 Subject: [PATCH 0409/1299] nrf/machine/adc: Allow to pass a Pin object in to ADC constructor. --- ports/nrf/modules/machine/adc.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ports/nrf/modules/machine/adc.c b/ports/nrf/modules/machine/adc.c index b543c94f3968c..e4885dd097920 100644 --- a/ports/nrf/modules/machine/adc.c +++ b/ports/nrf/modules/machine/adc.c @@ -91,10 +91,19 @@ void adc_init0(void) { } STATIC int adc_find(mp_obj_t id) { - // given an integer id - int adc_id = mp_obj_get_int(id); - - int adc_idx = adc_id; + int adc_idx; + if (mp_obj_is_int(id)) { + // Given an integer id + adc_idx = mp_obj_get_int(id); + } else { + // Assume it's a pin-compatible object and convert it to an ADC channel number + mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(id); + if (pin->adc_num & PIN_ADC1) { + adc_idx = pin->adc_channel; + } else { + mp_raise_ValueError("invalid Pin for ADC"); + } + } if (adc_idx >= 0 && adc_idx < MP_ARRAY_SIZE(machine_adc_obj) && machine_adc_obj[adc_idx].id != (uint8_t)-1) { From 9e90e2528b94f8e964d350cba7e7d2e050c06be5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 5 Sep 2019 19:20:04 +1000 Subject: [PATCH 0410/1299] nrf/machine/adc: Fix mapping of ADC channel to pin. --- ports/nrf/modules/machine/adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/nrf/modules/machine/adc.c b/ports/nrf/modules/machine/adc.c index e4885dd097920..fc5305e5242b8 100644 --- a/ports/nrf/modules/machine/adc.c +++ b/ports/nrf/modules/machine/adc.c @@ -146,7 +146,7 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s .acq_time = NRF_SAADC_ACQTIME_3US, .mode = NRF_SAADC_MODE_SINGLE_ENDED, .burst = NRF_SAADC_BURST_DISABLED, - .pin_p = self->id, // 0 - 7 + .pin_p = 1 + self->id, // pin_p=0 is AIN0, pin_p=8 is AIN7 .pin_n = NRF_SAADC_INPUT_DISABLED }; From 353ed7705f36e1f88b02c170cb2c578d80e2c622 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 23 Aug 2019 23:31:40 +1000 Subject: [PATCH 0411/1299] nrf/boards/make-pins.py: Fix gen of board pins to use correct index. It was previously not taking into account that the list of pins was sparse, so using the wrong index. The boards/X/pins.csv was generating the wrong data for machine.Pin.board. As part of this fix rename the variables to make it more clear what the list contains (only board pins). --- ports/nrf/boards/make-pins.py | 18 +++++++++++++----- ports/nrf/modules/machine/pin.c | 10 +++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/ports/nrf/boards/make-pins.py b/ports/nrf/boards/make-pins.py index 023b2161c8f0a..1844a06783f79 100644 --- a/ports/nrf/boards/make-pins.py +++ b/ports/nrf/boards/make-pins.py @@ -93,6 +93,7 @@ def __init__(self, pin): self.adc_num = 0 self.adc_channel = 0 self.board_pin = False + self.board_index = None def cpu_pin_name(self): return '{:s}{:d}'.format("P", self.pin) @@ -103,6 +104,9 @@ def is_board_pin(self): def set_is_board_pin(self): self.board_pin = True + def set_board_index(self, index): + self.board_index = index + def parse_adc(self, adc_str): if (adc_str[:3] != 'ADC'): return @@ -233,20 +237,24 @@ def parse_board_file(self, filename): def print_named(self, label, named_pins): print('STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label)) - index = 0 for named_pin in named_pins: pin = named_pin.pin() if pin.is_board_pin(): - print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&machine_pin_obj[{:d}]) }},'.format(named_pin.name(), index)) - index += 1 + print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&machine_board_pin_obj[{:d}]) }},'.format(named_pin.name(), pin.board_index)) print('};') print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label)); def print_const_table(self): + num_board_pins = 0 + for named_pin in self.cpu_pins: + pin = named_pin.pin() + if pin.is_board_pin(): + pin.set_board_index(num_board_pins) + num_board_pins += 1 print('') - print('const uint8_t machine_pin_num_of_pins = {:d};'.format(len(self.board_pins))) + print('const uint8_t machine_pin_num_of_board_pins = {:d};'.format(num_board_pins)) print('') - print('const pin_obj_t machine_pin_obj[{:d}] = {{'.format(len(self.board_pins))) + print('const pin_obj_t machine_board_pin_obj[{:d}] = {{'.format(num_board_pins)) for named_pin in self.cpu_pins: pin = named_pin.pin() if pin.is_board_pin(): diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c index 4e5b3434f96d6..f3a0bf07a6aae 100644 --- a/ports/nrf/modules/machine/pin.c +++ b/ports/nrf/modules/machine/pin.c @@ -37,8 +37,8 @@ #include "nrf_gpio.h" #include "nrfx_gpiote.h" -extern const pin_obj_t machine_pin_obj[]; -extern const uint8_t machine_pin_num_of_pins; +extern const pin_obj_t machine_board_pin_obj[]; +extern const uint8_t machine_pin_num_of_board_pins; /// \moduleref machine /// \class Pin - control I/O pins @@ -128,9 +128,9 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) { // If pin is SMALL_INT if (mp_obj_is_small_int(user_obj)) { uint8_t value = MP_OBJ_SMALL_INT_VALUE(user_obj); - for (uint8_t i = 0; i < machine_pin_num_of_pins; i++) { - if (machine_pin_obj[i].pin == value) { - return &machine_pin_obj[i]; + for (uint8_t i = 0; i < machine_pin_num_of_board_pins; i++) { + if (machine_board_pin_obj[i].pin == value) { + return &machine_board_pin_obj[i]; } } } From d36fc4682ebd8409bbcba00948da74b55bdeb3ce Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 23 Aug 2019 22:23:11 +1000 Subject: [PATCH 0412/1299] nrf/Makefile: Add support for flashing with a Black Magic Probe. Also rename "flash" target to "deploy" to match other ports (but provide "flash" as an alias for backwards compatibility). --- ports/nrf/Makefile | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index cc7b4f1260b77..c02109a156225 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -101,7 +101,7 @@ LDFLAGS += -Wl,--gc-sections endif -CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) +CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(INC) -Wall -Werror -g -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_MOD) CFLAGS += -fno-strict-aliasing CFLAGS += -Iboards/$(BOARD) @@ -254,7 +254,7 @@ OBJ += $(BUILD)/pins_gen.o $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os -.PHONY: all flash sd binary hex +.PHONY: all flash deploy sd binary hex all: binary hex @@ -276,7 +276,7 @@ FLASHER ?= ifeq ($(FLASHER),) -flash: $(BUILD)/$(OUTPUT_FILENAME).hex +deploy: $(BUILD)/$(OUTPUT_FILENAME).hex nrfjprog --program $< --sectorerase -f $(MCU_VARIANT) nrfjprog --reset -f $(MCU_VARIANT) @@ -288,7 +288,7 @@ sd: $(BUILD)/$(OUTPUT_FILENAME).hex else ifeq ($(FLASHER), pyocd) -flash: $(BUILD)/$(OUTPUT_FILENAME).hex +deploy: $(BUILD)/$(OUTPUT_FILENAME).hex pyocd-flashtool -t $(MCU_VARIANT) $< sd: $(BUILD)/$(OUTPUT_FILENAME).hex @@ -298,14 +298,47 @@ sd: $(BUILD)/$(OUTPUT_FILENAME).hex else ifeq ($(FLASHER), idap) -flash: $(BUILD)/$(OUTPUT_FILENAME).hex +deploy: $(BUILD)/$(OUTPUT_FILENAME).hex IDAPnRFPRog $< sd: $(BUILD)/$(OUTPUT_FILENAME).hex IDAPnRFPRog $(SOFTDEV_HEX) $< +else ifeq ($(FLASHER), bmp) + +BMP_PORT ?= /dev/ttyACM0 + +deploy: $(BUILD)/$(OUTPUT_FILENAME).elf + $(Q)$(GDB) \ + -ex 'target extended-remote $(BMP_PORT)' \ + -ex 'monitor tpwr enable' \ + -ex 'monitor swdp_scan' \ + -ex 'attach 1' \ + -ex 'set mem inaccessible-by-default off' \ + -ex 'load' \ + -ex 'kill' \ + -ex 'quit' \ + $< + +sd: $(BUILD)/$(OUTPUT_FILENAME).elf + $(Q)$(GDB) \ + -ex 'target extended-remote $(BMP_PORT)' \ + -ex 'monitor tpwr enable' \ + -ex 'monitor swdp_scan' \ + -ex 'attach 1' \ + -ex 'set mem inaccessible-by-default off' \ + -ex 'monitor erase_mass' \ + -ex 'load' \ + -ex 'file $(SOFTDEV_HEX)' \ + -ex 'load' \ + -ex 'kill' \ + -ex 'quit' \ + $< + endif +flash: deploy + $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(ECHO) "LINK $@" $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) From 1f52a6f8e4f0438c09081b930178df0b585f9eb1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 23 Aug 2019 23:30:58 +1000 Subject: [PATCH 0413/1299] nrf/boards: Add Particle Xenon board configuration (an nRF52840). --- ports/nrf/README.md | 14 +++- .../nrf/boards/particle_xenon/mpconfigboard.h | 70 +++++++++++++++++++ .../boards/particle_xenon/mpconfigboard.mk | 7 ++ ports/nrf/boards/particle_xenon/pins.csv | 38 ++++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 ports/nrf/boards/particle_xenon/mpconfigboard.h create mode 100644 ports/nrf/boards/particle_xenon/mpconfigboard.mk create mode 100644 ports/nrf/boards/particle_xenon/pins.csv diff --git a/ports/nrf/README.md b/ports/nrf/README.md index 2a1667a3eb2a0..df5904eb610fd 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -30,7 +30,7 @@ This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. * PCA10031 (dongle) * [WT51822-S4AT](http://www.wireless-tag.com/wireless_module/BLE/WT51822-S4AT.html) * nRF52832 - * [PCA10040](http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52%2Fdita%2Fnrf52%2Fdevelopment%2Fnrf52_dev_kit.html) + * [PCA10040](http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52%2Fdita%2Fnrf52%2Fdevelopment%2Fnrf52_dev_kit.html) * [Adafruit Feather nRF52](https://www.adafruit.com/product/3406) * [Thingy:52](http://www.nordicsemi.com/eng/Products/Nordic-Thingy-52) * [Arduino Primo](http://www.arduino.org/products/boards/arduino-primo) @@ -38,6 +38,7 @@ This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. * [BLUEIO-TAG-EVIM BLYST Nano Sensor board](https://www.crowdsupply.com/i-syst/blyst-nano) * nRF52840 * [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK) + * [Particle Xenon](https://docs.particle.io/xenon/) ## Compile and Flash @@ -71,7 +72,7 @@ the compilation: GNU ARM Embedded Toolchain 7.2.1/4Q17. It's recommended to use a toolchain after this release, for example 7.3.1/2Q18 or 8.2.1/4Q18. The alternative would be to build the target using the LTO=0 as described above. - + ## Compile and Flash with Bluetooth Stack First prepare the bluetooth folder by downloading Bluetooth LE stacks and headers: @@ -126,6 +127,7 @@ ibk_blyst_nano | s132 | Peripheral and Central | [IDAP] idk_blyst_nano | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) blueio_tag_evim | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) pca10056 | s140 | Peripheral and Central | [Segger](#segger-targets) +particle_xenon | s140 | Peripheral and Central | [Black Magic Probe](#black-magic-probe-targets) ## IDAP-M/IDAP-Link Targets @@ -153,6 +155,14 @@ Install the necessary tools to flash and debug using OpenOCD: sudo apt-get install openocd sudo pip install pyOCD +## Black Magic Probe Targets + +This requires no further dependencies other than `arm-none-eabi-gdb`. + +`make deploy` will use gdb to load and run new firmware. See +[this guide](https://github.com/blacksphere/blackmagic/wiki/Useful-GDB-commands) +for more tips about using the BMP with GDB. + ## Bluetooth LE REPL The port also implements a BLE REPL driver. This feature is disabled by default, as it will deactivate the UART REPL when activated. As some of the nRF devices only have one UART, using the BLE REPL free's the UART instance such that it can be used as a general UART peripheral not bound to REPL. diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h new file mode 100644 index 0000000000000..c2aabce48d7aa --- /dev/null +++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h @@ -0,0 +1,70 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jim Mussared + * + * 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. + */ + +#define MICROPY_HW_BOARD_NAME "XENON" +#define MICROPY_HW_MCU_NAME "NRF52840" +#define MICROPY_PY_SYS_PLATFORM "PARTICLE-XENON" + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_PWM (1) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_RTCOUNTER (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_TEMP (1) +#define MICROPY_PY_RANDOM_HW_RNG (1) + +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_LED_TRICOLOR (1) +#define MICROPY_HW_LED_PULLUP (1) + +#define MICROPY_HW_LED_RED (13) // LED1 +#define MICROPY_HW_LED_GREEN (14) // LED2 +#define MICROPY_HW_LED_BLUE (15) // LED3 + +// UART config +#define MICROPY_HW_UART1_RX (8) +#define MICROPY_HW_UART1_TX (6) +#define MICROPY_HW_UART1_CTS (32+2) +#define MICROPY_HW_UART1_RTS (32+1) +#define MICROPY_HW_UART1_HWFC (0) + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" + +#define MICROPY_HW_SPI0_SCK (32+15) +#define MICROPY_HW_SPI0_MOSI (32+13) +#define MICROPY_HW_SPI0_MISO (32+14) + +#define MICROPY_HW_PWM0_NAME "PWM0" +#define MICROPY_HW_PWM1_NAME "PWM1" +#define MICROPY_HW_PWM2_NAME "PWM2" +#if 0 +#define MICROPY_HW_PWM3_NAME "PWM3" +#endif + +#define HELP_TEXT_BOARD_LED "1,2,3" diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.mk b/ports/nrf/boards/particle_xenon/mpconfigboard.mk new file mode 100644 index 0000000000000..ca555d3932aa4 --- /dev/null +++ b/ports/nrf/boards/particle_xenon/mpconfigboard.mk @@ -0,0 +1,7 @@ +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52840 +SOFTDEV_VERSION = 6.1.1 +LD_FILES += boards/nrf52840_1M_256k.ld + +NRF_DEFINES += -DNRF52840_XXAA diff --git a/ports/nrf/boards/particle_xenon/pins.csv b/ports/nrf/boards/particle_xenon/pins.csv new file mode 100644 index 0000000000000..30f05c5564ff9 --- /dev/null +++ b/ports/nrf/boards/particle_xenon/pins.csv @@ -0,0 +1,38 @@ +LED1,P13 +LED2,P14 +LED3,P15 +A0,P3,ADC0_IN1 +A1,P4,ADC0_IN2 +A2,P28,ADC0_IN4 +A3,P29,ADC0_IN5 +A4,P30,ADC0_IN6 +A5,P31,ADC0_IN7 +SPI_SS,P31 +SPI_SCK,P47 +SPI_MOSI,P45 +SPI_MISO,P46 +SPI1_SCK,P33 +SPI1_MOSI,P34 +SPI1_MISO,P40 +UART1_RX,P8 +UART1_TX,P6 +UART2_RX,P42 +UART2_TX,P40 +SDA,P26 +SCL,P27 +SDA1,P33 +SCL1,P34 +D0,P26 +D1,P27 +D2,P33 +D3,P34 +D4,P40 +D5,P42 +D6,P43 +D7,P44 +D8,P35 +D9,P6 +D10,P8 +D11,P46 +D12,P45 +D13,P47 From fb73bdae6256451838ef48565030f181077584fe Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 5 Sep 2019 22:59:06 +1000 Subject: [PATCH 0414/1299] py/mkenv.mk: Add GDB variable. --- py/mkenv.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/py/mkenv.mk b/py/mkenv.mk index 46eedf988ab5d..0a59c2ac74ec0 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -49,6 +49,7 @@ PYTHON = python3 AS = $(CROSS_COMPILE)as CC = $(CROSS_COMPILE)gcc CXX = $(CROSS_COMPILE)g++ +GDB = $(CROSS_COMPILE)gdb LD = $(CROSS_COMPILE)ld OBJCOPY = $(CROSS_COMPILE)objcopy SIZE = $(CROSS_COMPILE)size From 62fe013a5f0d0719cfebd503c818dee2438778cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 6 Sep 2019 17:55:12 +1000 Subject: [PATCH 0415/1299] stm32/machine_adc: Improve operation of ADC for H7, L4 and WB MCUs. --- ports/stm32/machine_adc.c | 64 ++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 58c0133595545..416beeca4cb4f 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -72,9 +72,9 @@ static inline void adc_stabilisation_delay_us(uint32_t us) { STATIC void adc_wait_eoc(ADC_TypeDef *adc, int32_t timeout_ms) { uint32_t t0 = mp_hal_ticks_ms(); #if ADC_V2 - while (!(adc->ISR & ADC_FLAG_EOC)) + while (!(adc->ISR & ADC_ISR_EOC)) #else - while (!(adc->SR & ADC_FLAG_EOC)) + while (!(adc->SR & ADC_SR_EOC)) #endif { if (mp_hal_ticks_ms() - t0 > timeout_ms) { @@ -90,7 +90,9 @@ STATIC const uint8_t adc_cr_to_bits_table[] = {12, 10, 8, 6}; #endif STATIC void adc_config(ADC_TypeDef *adc, uint32_t bits) { + // Configure ADC clock source and enable ADC clock #if defined(STM32L4) || defined(STM32WB) + __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); __HAL_RCC_ADC_CLK_ENABLE(); #else if (adc == ADC1) { @@ -116,7 +118,43 @@ STATIC void adc_config(ADC_TypeDef *adc, uint32_t bits) { #endif #endif + // Configure clock mode + #if defined(STM32F0) + adc->CFGR2 = 1 << ADC_CFGR2_CKMODE_Pos; // PCLK/2 (synchronous clock mode) + #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L4) + ADC123_COMMON->CCR = 0; // ADCPR=PCLK/2 + #elif defined(STM32H7) + ADC12_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; + ADC3_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; + #elif defined(STM32L0) || defined(STM32WB) + ADC1_COMMON->CCR = 0; // ADCPR=PCLK/2 + #endif + + #if defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + if (adc->CR & ADC_CR_DEEPPWD) { + adc->CR = 0; // disable deep powerdown + } + #endif + + #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + if (!(adc->CR & ADC_CR_ADVREGEN)) { + adc->CR = ADC_CR_ADVREGEN; // enable VREG + #if defined(STM32H7) + mp_hal_delay_us(10); // T_ADCVREG_STUP + #elif defined(STM32L4) || defined(STM32WB) + mp_hal_delay_us(20); // T_ADCVREG_STUP + #endif + } + #endif + #if ADC_V2 + if (adc->CR == 0) { + // ADC hasn't been enabled so calibrate it + adc->CR |= ADC_CR_ADCAL; + while (adc->CR & ADC_CR_ADCAL) { + } + } + if (adc->CR & ADC_CR_ADEN) { // ADC enabled, need to disable it to change configuration if (adc->CR & ADC_CR_ADSTART) { @@ -130,17 +168,6 @@ STATIC void adc_config(ADC_TypeDef *adc, uint32_t bits) { } #endif - // TODO check all these - #if defined(STM32F0) - adc->CFGR2 = 1 << ADC_CFGR2_CKMODE_Pos; // PCLK/2 (synchronous clock mode) - #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L4) - ADC123_COMMON->CCR = 0; // ADCPR=PCLK/2 - #elif defined(STM32H7) - __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); - #elif defined(STM32L0) || defined(STM32WB) - ADC1_COMMON->CCR = 0; // ADCPR=PCLK/2 - #endif - // Find resolution, defaulting to last element in table uint32_t res; for (res = 0; res <= MP_ARRAY_SIZE(adc_cr_to_bits_table); ++res) { @@ -193,10 +220,11 @@ STATIC int adc_get_bits(ADC_TypeDef *adc) { STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t sample_time) { #if ADC_V2 if (!(adc->CR & ADC_CR_ADEN)) { - if (adc->CR) { + if (adc->CR & 0x3f) { // Cannot enable ADC with CR!=0 return; } + adc->ISR = ADC_ISR_ADRDY; // clear ADRDY adc->CR |= ADC_CR_ADEN; adc_stabilisation_delay_us(ADC_STAB_DELAY_US); while (!(adc->ISR & ADC_ISR_ADRDY)) { @@ -249,6 +277,7 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp #elif defined(STM32H7) || defined(STM32L4) || defined(STM32WB) #if defined(STM32H7) + adc->PCSEL |= 1 << channel; ADC_Common_TypeDef *adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON; #elif defined(STM32L4) ADC_Common_TypeDef *adc_common = ADC123_COMMON; @@ -263,7 +292,7 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp } else if (channel == ADC_CHANNEL_VBAT) { adc_common->CCR |= ADC_CCR_VBATEN; } - adc->SQR1 = (channel & 0x1f) << ADC_SQR1_SQ1_Pos | 1 << ADC_SQR1_L_Pos; + adc->SQR1 = (channel & 0x1f) << ADC_SQR1_SQ1_Pos | (1 - 1) << ADC_SQR1_L_Pos; __IO uint32_t *smpr; if (channel <= 9) { smpr = &adc->SMPR1; @@ -323,6 +352,11 @@ STATIC void machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_prin unsigned adc_id = 1; #else unsigned adc_id = (self->adc - ADC1) / (ADC2 - ADC1) + 1; + #if defined(STM32H7) + if (self->adc == ADC3) { + adc_id = 3; + } + #endif #endif mp_printf(print, "", adc_id, self->channel); } From bd2e46e0a575029367caed118c15a73a5f9851b5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 6 Sep 2019 17:56:34 +1000 Subject: [PATCH 0416/1299] stm32/boards/stm32wb55_af.csv: Fix ADC pin-channel function mapping. --- ports/stm32/boards/stm32wb55_af.csv | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ports/stm32/boards/stm32wb55_af.csv b/ports/stm32/boards/stm32wb55_af.csv index 6e4ddd9608250..074c33089261d 100644 --- a/ports/stm32/boards/stm32wb55_af.csv +++ b/ports/stm32/boards/stm32wb55_af.csv @@ -1,23 +1,23 @@ Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS_AF,TIM1/TIM2/LPTIM1,TIM1/TIM2,SPI2/SAI1/TIM1,I2C1/I2C3,SPI1/SPI2,RF,USART1,LPUART1,TSC,USB/QUADSPI,LCD,COMP1/COMP2/TIM1,SAI1,TIM2/TIM16/TIM17/LPTIM2,EVENTOUT,ADC -PortA,PA0,,TIM2_CH1,,,,,,,,,,,COMP1_OUT,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC123_IN0 -PortA,PA1,,TIM2_CH2,,,I2C1_SMBA,SPI1_SCK,,,,,,LCD_SEG0,,,,EVENTOUT,ADC123_IN1 -PortA,PA2,LSCO,TIM2_CH3,,,,,,,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG1,COMP2_OUT,,,EVENTOUT,ADC123_IN2 -PortA,PA3,,TIM2_CH4,,SAI1_PDM_CK1,,,,,LPUART1_RX,,QUADSPI_CLK,LCD_SEG2,,SAI1_MCLK_A,,EVENTOUT,ADC123_IN3 -PortA,PA4,,,,,,SPI1_NSS,,,,,,LCD_SEG5,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC12_IN4 -PortA,PA5,,TIM2_CH1,TIM2_ETR,,,SPI1_SCK,,,,,,,,SAI1_SD_B,LPTIM2_ETR,EVENTOUT,ADC12_IN5 -PortA,PA6,,TIM1_BKIN,,,,SPI1_MISO,,,LPUART1_CTS,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN,,TIM16_CH1,EVENTOUT,ADC12_IN6 -PortA,PA7,,TIM1_CH1N,,,I2C3_SCL,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,COMP2_OUT,,TIM17_CH1,EVENTOUT,ADC12_IN7 -PortA,PA8,MCO,TIM1_CH1,,SAI1_PDM_CK2,,,,USART1_CK,,,,LCD_COM0,,SAI1_SCK_A,LPTIM2_OUT,EVENTOUT, -PortA,PA9,,TIM1_CH2,,SAI1_PDM_DI2,I2C1_SCL,SPI2_SCK,,USART1_TX,,,,LCD_COM1,,SAI1_FS_A,,EVENTOUT, +PortA,PA0,,TIM2_CH1,,,,,,,,,,,COMP1_OUT,SAI1_EXTCLK,TIM2_ETR,EVENTOUT,ADC1_IN5 +PortA,PA1,,TIM2_CH2,,,I2C1_SMBA,SPI1_SCK,,,,,,LCD_SEG0,,,,EVENTOUT,ADC1_IN6 +PortA,PA2,LSCO,TIM2_CH3,,,,,,,LPUART1_TX,,QUADSPI_BK1_NCS,LCD_SEG1,COMP2_OUT,,,EVENTOUT,ADC1_IN7 +PortA,PA3,,TIM2_CH4,,SAI1_PDM_CK1,,,,,LPUART1_RX,,QUADSPI_CLK,LCD_SEG2,,SAI1_MCLK_A,,EVENTOUT,ADC1_IN8 +PortA,PA4,,,,,,SPI1_NSS,,,,,,LCD_SEG5,,SAI1_FS_B,LPTIM2_OUT,EVENTOUT,ADC1_IN9 +PortA,PA5,,TIM2_CH1,TIM2_ETR,,,SPI1_SCK,,,,,,,,SAI1_SD_B,LPTIM2_ETR,EVENTOUT,ADC1_IN10 +PortA,PA6,,TIM1_BKIN,,,,SPI1_MISO,,,LPUART1_CTS,,QUADSPI_BK1_IO3,LCD_SEG3,TIM1_BKIN,,TIM16_CH1,EVENTOUT,ADC1_IN11 +PortA,PA7,,TIM1_CH1N,,,I2C3_SCL,SPI1_MOSI,,,,,QUADSPI_BK1_IO2,LCD_SEG4,COMP2_OUT,,TIM17_CH1,EVENTOUT,ADC1_IN12 +PortA,PA8,MCO,TIM1_CH1,,SAI1_PDM_CK2,,,,USART1_CK,,,,LCD_COM0,,SAI1_SCK_A,LPTIM2_OUT,EVENTOUT,ADC1_IN15 +PortA,PA9,,TIM1_CH2,,SAI1_PDM_DI2,I2C1_SCL,SPI2_SCK,,USART1_TX,,,,LCD_COM1,,SAI1_FS_A,,EVENTOUT,ADC1_IN16 PortA,PA10,,TIM1_CH3,,SAI1_PDM_DI1,I2C1_SDA,,,USART1_RX,,,USB_CRS_SYNC,LCD_COM2,,SAI1_SD_A,TIM17_BKIN,EVENTOUT, PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,,USART1_CTS,,,USB_DM,,TIM1_BKIN2,,,EVENTOUT, PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS_DE,LPUART1_RX,,USB_DP,,,,,EVENTOUT, PortA,PA13,JTMS/SWDIO,,,,,,,,IR_OUT,,USB_NOE,,,SAI1_SD_B,,EVENTOUT, PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,LCD_SEG5,,SAI1_FS_B,,EVENTOUT, PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,,SPI1_NSS,,,,TSC_G3_IO1,,LCD_SEG17,,,,EVENTOUT, -PortB,PB0,,,,,,,EXT_PA_TX,,,,,,COMP1_OUT,,,EVENTOUT,ADC12_IN8 -PortB,PB1,,,,,,,,,LPUART1_RTS_DE,,,,,,LPTIM2_IN1,EVENTOUT,ADC12_IN9 +PortB,PB0,,,,,,,EXT_PA_TX,,,,,,COMP1_OUT,,,EVENTOUT, +PortB,PB1,,,,,,,,,LPUART1_RTS_DE,,,,,,LPTIM2_IN1,EVENTOUT, PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,SPI1_NSS,,,,,,LCD_VLCD,,SAI1_EXTCLK,,EVENTOUT, PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,,USART1_RTS_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT, PortB,PB4,NJTRST,,,,I2C3_SDA,SPI1_MISO,,USART1_CTS,,TSC_G2_IO1,,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT, @@ -32,12 +32,12 @@ PortB,PB12,,TIM1_BKIN,,TIM1_BKIN,I2C3_SMBA,SPI2_NSS,,,LPUART1_RTS,TSC_G1_IO1,,LC PortB,PB13,,TIM1_CH1N,,,I2C3_SCL,SPI2_SCK,,,LPUART1_CTS,TSC_G1_IO2,,LCD_SEG13,,SAI1_SCK_A,,EVENTOUT, PortB,PB14,,TIM1_CH2N,,,I2C3_SDA,SPI2_MISO,,,,TSC_G1_IO3,,LCD_SEG14,,SAI1_MCLK_A,,EVENTOUT, PortB,PB15,RTC_REFIN,TIM1_CH3N,,,,SPI2_MOSI,,,,TSC_G1_IO4,,LCD_SEG15,,SAI1_SD_A,,EVENTOUT, -PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC123_IN10 -PortC,PC1,,LPTIM1_OUT,,SPI2_MOSI,I2C3_SDA,,,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT,ADC123_IN11 -PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,,,,,,LCD_SEG20,,,,EVENTOUT,ADC123_IN12 -PortC,PC3,,LPTIM1_ETR,,SAI1_PDM_DI1,,SPI2_MOSI,,,,,,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC123_IN13 -PortC,PC4,,,,,,,,,,,,LCD_SEG22,,,,EVENTOUT,ADC12_IN14 -PortC,PC5,,,,SAI1_PDM_DI3,,,,,,,,LCD_SEG23,,,,EVENTOUT,ADC12_IN15 +PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC1_IN1 +PortC,PC1,,LPTIM1_OUT,,SPI2_MOSI,I2C3_SDA,,,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT,ADC1_IN2 +PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,,,,,,LCD_SEG20,,,,EVENTOUT,ADC1_IN3 +PortC,PC3,,LPTIM1_ETR,,SAI1_PDM_DI1,,SPI2_MOSI,,,,,,LCD_VLCD,,SAI1_SD_A,LPTIM2_ETR,EVENTOUT,ADC1_IN4 +PortC,PC4,,,,,,,,,,,,LCD_SEG22,,,,EVENTOUT,ADC1_IN13 +PortC,PC5,,,,SAI1_PDM_DI3,,,,,,,,LCD_SEG23,,,,EVENTOUT,ADC1_IN14 PortC,PC6,,,,,,,,,,TSC_G4_IO1,,LCD_SEG24,,,,EVENTOUT, PortC,PC7,,,,,,,,,,TSC_G4_IO2,,LCD_SEG25,,,,EVENTOUT, PortC,PC8,,,,,,,,,,TSC_G4_IO3,,LCD_SEG26,,,,EVENTOUT, From c69f58e6b97b954d06734797f06feeab4e510855 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 6 Sep 2019 23:55:15 +1000 Subject: [PATCH 0417/1299] tools/mpy-tool.py: Fix freezing of non-bytecode funcs with settrace. Only bytecode functions can be profiled at this stage. Native functions (eg inline assembler) may not even have a valid prelude. Fixes issue #5075. --- tools/mpy-tool.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index e5c8f09597a3d..e159165f1450c 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -412,22 +412,23 @@ def freeze_module(self, qstr_links=(), type_sig=0): print(' .fun_data_len = %u,' % len(self.bytecode)) print(' .n_obj = %u,' % len(self.objs)) print(' .n_raw_code = %u,' % len(self.raw_codes)) - print(' #if MICROPY_PY_SYS_SETTRACE') - print(' .prelude = {') - print(' .n_state = %u,' % self.prelude[0]) - print(' .n_exc_stack = %u,' % self.prelude[1]) - print(' .scope_flags = %u,' % self.prelude[2]) - print(' .n_pos_args = %u,' % self.prelude[3]) - print(' .n_kwonly_args = %u,' % self.prelude[4]) - print(' .n_def_pos_args = %u,' % self.prelude[5]) - print(' .qstr_block_name = %s,' % self.simple_name.qstr_id) - print(' .qstr_source_file = %s,' % self.source_file.qstr_id) - print(' .line_info = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO - print(' .locals = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO - print(' .opcodes = fun_data_%s + %u,' % (self.escaped_name, self.ip)) - print(' },') - print(' .line_of_definition = %u,' % 0) # TODO - print(' #endif') + if self.code_kind == MP_CODE_BYTECODE: + print(' #if MICROPY_PY_SYS_SETTRACE') + print(' .prelude = {') + print(' .n_state = %u,' % self.prelude[0]) + print(' .n_exc_stack = %u,' % self.prelude[1]) + print(' .scope_flags = %u,' % self.prelude[2]) + print(' .n_pos_args = %u,' % self.prelude[3]) + print(' .n_kwonly_args = %u,' % self.prelude[4]) + print(' .n_def_pos_args = %u,' % self.prelude[5]) + print(' .qstr_block_name = %s,' % self.simple_name.qstr_id) + print(' .qstr_source_file = %s,' % self.source_file.qstr_id) + print(' .line_info = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO + print(' .locals = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO + print(' .opcodes = fun_data_%s + %u,' % (self.escaped_name, self.ip)) + print(' },') + print(' .line_of_definition = %u,' % 0) # TODO + print(' #endif') print(' #if MICROPY_EMIT_MACHINE_CODE') print(' .prelude_offset = %u,' % self.prelude_offset) print(' .n_qstr = %u,' % len(qstr_links)) From 5641aa55dddbdf312a1e8dbb8c3936115683840a Mon Sep 17 00:00:00 2001 From: Braden Mars Date: Sat, 7 Sep 2019 01:28:11 -0500 Subject: [PATCH 0418/1299] esp32: Update to use ESP IDF v3.3 Includes patches for CVE-2019-12586 & CVE-2019-12587 --- ports/esp32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index cf1b24bfc8afa..1e0298452010f 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -49,7 +49,7 @@ SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined SDKCONFIG_H = $(BUILD)/sdkconfig.h # the git hash of the currently supported ESP IDF version -ESPIDF_SUPHASH := 6b3da6b1882f3b72e904cc90be67e9c4e3f369a9 +ESPIDF_SUPHASH := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df # paths to ESP IDF and its components ifeq ($(ESPIDF),) From e9af6f5f886337d0a366ac4d7f4a03ee1117cde0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 30 Aug 2019 17:15:01 +1000 Subject: [PATCH 0419/1299] esp32/boards/TINYPICO: Switch to use QIO and 80MHz for SPI interface. --- ports/esp32/boards/TINYPICO/mpconfigboard.mk | 3 +++ ports/esp32/boards/TINYPICO/sdkconfig.board | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 ports/esp32/boards/TINYPICO/sdkconfig.board diff --git a/ports/esp32/boards/TINYPICO/mpconfigboard.mk b/ports/esp32/boards/TINYPICO/mpconfigboard.mk index 59aa75f8571b9..2efdba0f39d9f 100644 --- a/ports/esp32/boards/TINYPICO/mpconfigboard.mk +++ b/ports/esp32/boards/TINYPICO/mpconfigboard.mk @@ -1,2 +1,5 @@ +FLASH_FREQ = 80m + SDKCONFIG += boards/sdkconfig.base SDKCONFIG += boards/sdkconfig.spiram +SDKCONFIG += boards/TINYPICO/sdkconfig.board diff --git a/ports/esp32/boards/TINYPICO/sdkconfig.board b/ports/esp32/boards/TINYPICO/sdkconfig.board new file mode 100644 index 0000000000000..ea4fc9b5cd51b --- /dev/null +++ b/ports/esp32/boards/TINYPICO/sdkconfig.board @@ -0,0 +1,3 @@ +CONFIG_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_SPIRAM_SPEED_80M=y From 380048df64255e869d168b0bf4ebc4b6138a6eb2 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Fri, 6 Sep 2019 10:56:03 +1000 Subject: [PATCH 0420/1299] windows/Makefile: Make use of CFLAGS_EXTRA, LDFLAGS_EXTRA and SRC_MOD. To be consistent with the unix port. --- ports/windows/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/windows/Makefile b/ports/windows/Makefile index 88d103e7b0f19..e65c09c53ab6a 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -15,8 +15,8 @@ INC += -I$(TOP) INC += -I$(BUILD) # compiler settings -CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) -LDFLAGS = $(LDFLAGS_MOD) -lm +CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +LDFLAGS = $(LDFLAGS_MOD) -lm $(LDFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG @@ -40,6 +40,7 @@ SRC_C = \ realpath.c \ init.c \ sleep.c \ + $(SRC_MOD) OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) From ea060a42e9e00052564eb27bd9aa474b01fac9ae Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 7 Sep 2019 12:42:11 +1000 Subject: [PATCH 0421/1299] py/vm: Factor cached map lookup code to inline function. To reduce code duplication and allow to more easily modify this function. --- py/vm.c | 102 ++++++++++++++++++++++++-------------------------------- 1 file changed, 44 insertions(+), 58 deletions(-) diff --git a/py/vm.c b/py/vm.c index 9abad8d83fe7b..63869d9265dbb 100644 --- a/py/vm.c +++ b/py/vm.c @@ -158,6 +158,23 @@ #define TRACE_TICK(current_ip, current_sp, is_exception) #endif // MICROPY_PY_SYS_SETTRACE +#if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE +static inline mp_map_elem_t *mp_map_cached_lookup(mp_map_t *map, qstr qst, uint8_t *idx_cache) { + size_t idx = *idx_cache; + mp_obj_t key = MP_OBJ_NEW_QSTR(qst); + mp_map_elem_t *elem = NULL; + if (idx < map->alloc && map->table[idx].key == key) { + elem = &map->table[idx]; + } else { + elem = mp_map_lookup(map, key, MP_MAP_LOOKUP); + if (elem != NULL) { + *idx_cache = (elem - &map->table[0]) & 0xff; + } + } + return elem; +} +#endif + // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc) // sp points to bottom of stack which grows up // returns: @@ -333,19 +350,14 @@ FRAME_SETUP(); ENTRY(MP_BC_LOAD_NAME): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; - mp_obj_t key = MP_OBJ_NEW_QSTR(qst); - mp_uint_t x = *ip; - if (x < mp_locals_get()->map.alloc && mp_locals_get()->map.table[x].key == key) { - PUSH(mp_locals_get()->map.table[x].value); + mp_map_elem_t *elem = mp_map_cached_lookup(&mp_locals_get()->map, qst, (uint8_t*)ip); + mp_obj_t obj; + if (elem != NULL) { + obj = elem->value; } else { - mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); - if (elem != NULL) { - *(byte*)ip = (elem - &mp_locals_get()->map.table[0]) & 0xff; - PUSH(elem->value); - } else { - PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key))); - } + obj = mp_load_name(qst); } + PUSH(obj); ip++; DISPATCH(); } @@ -362,19 +374,14 @@ FRAME_SETUP(); ENTRY(MP_BC_LOAD_GLOBAL): { MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; - mp_obj_t key = MP_OBJ_NEW_QSTR(qst); - mp_uint_t x = *ip; - if (x < mp_globals_get()->map.alloc && mp_globals_get()->map.table[x].key == key) { - PUSH(mp_globals_get()->map.table[x].value); + mp_map_elem_t *elem = mp_map_cached_lookup(&mp_globals_get()->map, qst, (uint8_t*)ip); + mp_obj_t obj; + if (elem != NULL) { + obj = elem->value; } else { - mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); - if (elem != NULL) { - *(byte*)ip = (elem - &mp_globals_get()->map.table[0]) & 0xff; - PUSH(elem->value); - } else { - PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key))); - } + obj = mp_load_global(qst); } + PUSH(obj); ip++; DISPATCH(); } @@ -394,27 +401,18 @@ FRAME_SETUP(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; mp_obj_t top = TOP(); + mp_map_elem_t *elem = NULL; if (mp_obj_is_instance_type(mp_obj_get_type(top))) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(top); - mp_uint_t x = *ip; - mp_obj_t key = MP_OBJ_NEW_QSTR(qst); - mp_map_elem_t *elem; - if (x < self->members.alloc && self->members.table[x].key == key) { - elem = &self->members.table[x]; - } else { - elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP); - if (elem != NULL) { - *(byte*)ip = elem - &self->members.table[0]; - } else { - goto load_attr_cache_fail; - } - } - SET_TOP(elem->value); - ip++; - DISPATCH(); + elem = mp_map_cached_lookup(&self->members, qst, (uint8_t*)ip); } - load_attr_cache_fail: - SET_TOP(mp_load_attr(top, qst)); + mp_obj_t obj; + if (elem != NULL) { + obj = elem->value; + } else { + obj = mp_load_attr(top, qst); + } + SET_TOP(obj); ip++; DISPATCH(); } @@ -493,29 +491,17 @@ FRAME_SETUP(); FRAME_UPDATE(); MARK_EXC_IP_SELECTIVE(); DECODE_QSTR; + mp_map_elem_t *elem = NULL; mp_obj_t top = TOP(); if (mp_obj_is_instance_type(mp_obj_get_type(top)) && sp[-1] != MP_OBJ_NULL) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(top); - mp_uint_t x = *ip; - mp_obj_t key = MP_OBJ_NEW_QSTR(qst); - mp_map_elem_t *elem; - if (x < self->members.alloc && self->members.table[x].key == key) { - elem = &self->members.table[x]; - } else { - elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP); - if (elem != NULL) { - *(byte*)ip = elem - &self->members.table[0]; - } else { - goto store_attr_cache_fail; - } - } + elem = mp_map_cached_lookup(&self->members, qst, (uint8_t*)ip); + } + if (elem != NULL) { elem->value = sp[-1]; - sp -= 2; - ip++; - DISPATCH(); + } else { + mp_store_attr(sp[0], qst, sp[-1]); } - store_attr_cache_fail: - mp_store_attr(sp[0], qst, sp[-1]); sp -= 2; ip++; DISPATCH(); From a605b537024c54a41717552155b977f5bcf7b5e5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Sep 2019 15:51:31 -0700 Subject: [PATCH 0422/1299] stm32/mboot: Support boards with only two LEDs. Mboot currently requires at least three LEDs to display each of the four states. However, since there are only four possible states, the states can be displayed via binary counting on only 2 LEDs (if only 2 are available). The existing patterns are still used for 3 or 4 LEDs. --- ports/stm32/mboot/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c index fcd43edc7f3ea..a0f1f1eacec3d 100644 --- a/ports/stm32/mboot/main.c +++ b/ports/stm32/mboot/main.c @@ -408,7 +408,9 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) { #define LED0 MICROPY_HW_LED1 #define LED1 MICROPY_HW_LED2 +#ifdef MICROPY_HW_LED3 #define LED2 MICROPY_HW_LED3 +#endif #ifdef MICROPY_HW_LED4 #define LED3 MICROPY_HW_LED4 #endif @@ -416,7 +418,9 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) { void led_init(void) { mp_hal_pin_output(LED0); mp_hal_pin_output(LED1); + #ifdef LED2 mp_hal_pin_output(LED2); + #endif #ifdef LED3 mp_hal_pin_output(LED3); #endif @@ -436,7 +440,9 @@ void led_state(int led, int val) { void led_state_all(unsigned int mask) { led_state(LED0, mask & 1); led_state(LED1, mask & 2); + #ifdef LED2 led_state(LED2, mask & 4); + #endif #ifdef LED3 led_state(LED3, mask & 8); #endif @@ -1345,11 +1351,15 @@ static int pyb_usbdd_shutdown(void) { #define RESET_MODE_NUM_STATES (4) #define RESET_MODE_TIMEOUT_CYCLES (8) +#ifdef LED2 #ifdef LED3 #define RESET_MODE_LED_STATES 0x8421 #else #define RESET_MODE_LED_STATES 0x7421 #endif +#else +#define RESET_MODE_LED_STATES 0x3210 +#endif static int get_reset_mode(void) { usrbtn_init(); From 2b07f56c2b6fecb4074d461f7ec50e6e9975fcbe Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 11:53:00 +1000 Subject: [PATCH 0423/1299] stm32/boards/NUCLEO_L073RZ: Fix typo in MCU name. --- ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h index ff4be4a27707e..e20dff677125b 100644 --- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h @@ -3,7 +3,7 @@ */ #define MICROPY_HW_BOARD_NAME "NUCLEO-L073RZ" -#define MICROPY_HW_MCU_NAME "STM32F073RZT6" +#define MICROPY_HW_MCU_NAME "STM32L073RZT6" #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) From 50636e5296c2eb837a5c29941b392adeaab60d94 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 13:22:35 +1000 Subject: [PATCH 0424/1299] docs/library/pyb.rst: Update docs for pyb.usb_mode() function. --- docs/library/pyb.rst | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst index 1e1e9ffaab58f..acb8fe450efd6 100644 --- a/docs/library/pyb.rst +++ b/docs/library/pyb.rst @@ -259,14 +259,12 @@ Miscellaneous functions Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU. -.. function:: usb_mode([modestr], vid=0xf055, pid=0x9801, hid=pyb.hid_mouse) +.. function:: usb_mode([modestr], port=-1, vid=0xf055, pid=-1, msc=(), hid=pyb.hid_mouse, high_speed=False) If called with no arguments, return the current USB mode as a string. - If called with ``modestr`` provided, attempts to set USB mode. - This can only be done when called from ``boot.py`` before - :meth:`pyb.main()` has been called. The following values of - ``modestr`` are understood: + If called with *modestr* provided, attempts to configure the USB mode. + The following values of *modestr* are understood: - ``None``: disables USB - ``'VCP'``: enable with VCP (Virtual COM Port) interface @@ -277,16 +275,28 @@ Miscellaneous functions For backwards compatibility, ``'CDC'`` is understood to mean ``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``). - The ``vid`` and ``pid`` parameters allow you to specify the VID - (vendor id) and PID (product id). + The *port* parameter should be an integer (0, 1, ...) and selects which + USB port to use if the board supports multiple ports. A value of -1 uses + the default or automatically selected port. + + The *vid* and *pid* parameters allow you to specify the VID (vendor id) + and PID (product id). A *pid* value of -1 will select a PID based on the + value of *modestr*. + + If enabling MSC mode, the *msc* parameter can be used to specify a list + of SCSI LUNs to expose on the mass storage interface. For example + ``msc=(pyb.Flash(), pyb.SDCard())``. If enabling HID mode, you may also specify the HID details by - passing the ``hid`` keyword parameter. It takes a tuple of + passing the *hid* keyword parameter. It takes a tuple of (subclass, protocol, max packet length, polling interval, report descriptor). By default it will set appropriate values for a USB mouse. There is also a ``pyb.hid_keyboard`` constant, which is an appropriate tuple for a USB keyboard. + The *high_speed* parameter, when set to ``True``, enables USB HS mode if + it is supported by the hardware. + Classes ------- From f9d142523c48af1cb9c83d1dfbc320cb9c2000c6 Mon Sep 17 00:00:00 2001 From: Christopher Wilson Date: Mon, 22 Jul 2019 09:05:31 -0700 Subject: [PATCH 0425/1299] stm32/boards/MIKROE_CLICKER2_STM32: Add MikroElektronika Clicker2 board. - STM32F407VGT6 (1MB of Flash, 192+4 Kbytes of SRAM) - 5V (via USB) or Li-Polymer Battery (3.7V) power input - 2 x LEDs - 2 x user switches - 2 x mikroBUS sockets - 2 x 1x26 mikromedia-compatible headers (52 pins) https://www.mikroe.com/clicker-2-stm32f4 --- .../MIKROE_CLICKER2_STM32/mpconfigboard.h | 85 ++++++++++++++++++ .../MIKROE_CLICKER2_STM32/mpconfigboard.mk | 13 +++ .../boards/MIKROE_CLICKER2_STM32/pins.csv | 88 +++++++++++++++++++ .../stm32f4xx_hal_conf.h | 19 ++++ 4 files changed, 205 insertions(+) create mode 100644 ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h create mode 100644 ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.mk create mode 100644 ports/stm32/boards/MIKROE_CLICKER2_STM32/pins.csv create mode 100644 ports/stm32/boards/MIKROE_CLICKER2_STM32/stm32f4xx_hal_conf.h diff --git a/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h b/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h new file mode 100644 index 0000000000000..eb622cd296a84 --- /dev/null +++ b/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.h @@ -0,0 +1,85 @@ +#define MICROPY_HW_BOARD_NAME "MIKROE_CLICKER2_STM32" +#define MICROPY_HW_MCU_NAME "STM32F407" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) + +// HSE is 25MHz +#define MICROPY_HW_CLK_PLLM (25) +#define MICROPY_HW_CLK_PLLN (336) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (7) +#define MICROPY_HW_CLK_LAST_FREQ (1) + +// The board has a 32kHz crystal for the RTC +#define MICROPY_HW_RTC_USE_LSE (1) +#define MICROPY_HW_RTC_USE_US (0) +#define MICROPY_HW_RTC_USE_CALOUT (0) // turn on/off PC13 512Hz output + +// UART config +// mikroBUS slot 1 +#define MICROPY_HW_UART2_NAME "SLOT1" +#define MICROPY_HW_UART2_TX (pin_D5) +#define MICROPY_HW_UART2_RX (pin_D6) +// mikroBUS slot 2 +#define MICROPY_HW_UART3_NAME "SLOT2" +#define MICROPY_HW_UART3_TX (pin_D8) +#define MICROPY_HW_UART3_RX (pin_D9) +// HDR2 +#define MICROPY_HW_UART4_NAME "HDR2" +#define MICROPY_HW_UART4_TX (pin_A0) +#define MICROPY_HW_UART4_RX (pin_A1) + +// I2C buses +// mikroBUS slot 2 / HDR2 +#define MICROPY_HW_I2C2_NAME "SLOT2" +#define MICROPY_HW_I2C2_SCL (pin_B10) +#define MICROPY_HW_I2C2_SDA (pin_B11) +// mikroBUS slot 1 +#define MICROPY_HW_I2C3_NAME "SLOT1" +#define MICROPY_HW_I2C3_SCL (pin_A8) +#define MICROPY_HW_I2C3_SDA (pin_C9) + +// SPI buses +// mikroBUS slot 2 / HDR1 +#define MICROPY_HW_SPI2_NAME "SLOT2" +#define MICROPY_HW_SPI2_NSS (pin_E11) +#define MICROPY_HW_SPI2_SCK (pin_B13) +#define MICROPY_HW_SPI2_MISO (pin_B14) +#define MICROPY_HW_SPI2_MOSI (pin_B15) +// mikroBUS slot 1 +#define MICROPY_HW_SPI3_NAME "SLOT1" +#define MICROPY_HW_SPI3_NSS (pin_E8) +#define MICROPY_HW_SPI3_SCK (pin_C10) +#define MICROPY_HW_SPI3_MISO (pin_C11) +#define MICROPY_HW_SPI3_MOSI (pin_C12) + +// USRSW is pulled high; pressing the button makes the input go low +#define MICROPY_HW_USRSW_PIN (pin_E0) +#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// LEDs +#define MICROPY_HW_LED1 (pin_E12) // red +#define MICROPY_HW_LED2 (pin_E15) // red +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// USB config +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) + +// Bootloader configuration (only needed if Mboot is used) +#define MBOOT_I2C_PERIPH_ID 2 +#define MBOOT_I2C_SCL (pin_B10) +#define MBOOT_I2C_SDA (pin_B11) +#define MBOOT_I2C_ALTFUNC (4) +#define MBOOT_BOOTPIN_PIN (pin_A10) +#define MBOOT_BOOTPIN_PULL (MP_HAL_PIN_PULL_NONE) +#define MBOOT_BOOTPIN_ACTIVE (0) +#define MBOOT_FSLOAD (1) diff --git a/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.mk b/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.mk new file mode 100644 index 0000000000000..aa52f21162c31 --- /dev/null +++ b/ports/stm32/boards/MIKROE_CLICKER2_STM32/mpconfigboard.mk @@ -0,0 +1,13 @@ +MCU_SERIES = f4 +CMSIS_MCU = STM32F407xx +AF_FILE = boards/stm32f405_af.csv +ifeq ($(USE_MBOOT),1) +# When using Mboot all the text goes together after the filesystem +LD_FILES = boards/stm32f405.ld boards/common_blifs.ld +TEXT0_ADDR = 0x08020000 +else +# When not using Mboot the ISR text goes first, then the rest after the filesystem +LD_FILES = boards/stm32f405.ld boards/common_ifs.ld +TEXT0_ADDR = 0x08000000 +TEXT1_ADDR = 0x08020000 +endif diff --git a/ports/stm32/boards/MIKROE_CLICKER2_STM32/pins.csv b/ports/stm32/boards/MIKROE_CLICKER2_STM32/pins.csv new file mode 100644 index 0000000000000..09e1ccfb4b19b --- /dev/null +++ b/ports/stm32/boards/MIKROE_CLICKER2_STM32/pins.csv @@ -0,0 +1,88 @@ +MB1_AN,PA2 +MB1_RST,PE7 +MB1_CS,PE8 +MB1_SCK,PC10 +MB1_MISO,PC11 +MB1_MOSI,PC12 +MB1_PWM,PE9 +MB1_INT,PE10 +MB1_RX,PD6 +MB1_TX,PD5 +MB1_SCL,PA8 +MB1_SDA,PC9 +MB2_AN,PA3 +MB2_RST,PE13 +MB2_CS,PE11 +MB2_SCK,PB13 +MB2_MISO,PB14 +MB2_MOSI,PB15 +MB2_PWM,PD12 +MB2_INT,PE14 +MB2_RX,PD9 +MB2_TX,PD8 +MB2_SCL,PB10 +MB2_SDA,PB11 +PIN1,VSYS +PIN2,GND +PIN3,PC0 +PIN4,PC1 +PIN5,PC2 +PIN6,PC3 +PIN7,PB1 +PIN8,PA4 +PIN9,PC4 +PIN10,PD3 +PIN11,PD1 +PIN12,PD2 +PIN13,PD0 +PIN14,PC8 +PIN15,PD15 +PIN16,PD14 +PIN17,PD13 +PIN18,PB7 +PIN19,PC7 +PIN20,PD11 +PIN21,PD10 +PIN22,PB13 +PIN23,PB14 +PIN24,PB15 +PIN25,3.3V +PIN26,GND +PIN27,RST +PIN28,GND +PIN30,NC +PIN31,PB9 +PIN32,PB8 +PIN33,PE5 +PIN34,PB0 +PIN35,PA5 +PIN36,PA6 +PIN37,PA7 +PIN38,PE1 +PIN39,PE2 +PIN40,PE3 +PIN41,PE4 +PIN42,PE6 +PIN43,PB6 +PIN44,PB5 +PIN45,PD7 +PIN46,PC13 +PIN47,PA1 +PIN48,PA0 +PIN49,PB10 +PIN50,PB11 +PIN51,3.3V +PIN52,GND +OSC32_OUT,PC15 +OSC32_IN,PC14 +VSENSE,PC5 +SENSEL,PB12 +FAULT,PC6 +BATSTAT,PD4 +LD1,PE12 +LD2,PE15 +T2,PE0 +T3,PA10 +USB_VBUS,PA9 +USB_DM,PA11 +USB_DP,PA12 \ No newline at end of file diff --git a/ports/stm32/boards/MIKROE_CLICKER2_STM32/stm32f4xx_hal_conf.h b/ports/stm32/boards/MIKROE_CLICKER2_STM32/stm32f4xx_hal_conf.h new file mode 100644 index 0000000000000..f186d5a29228c --- /dev/null +++ b/ports/stm32/boards/MIKROE_CLICKER2_STM32/stm32f4xx_hal_conf.h @@ -0,0 +1,19 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H + +#include "boards/stm32f4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (25000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H From 31de44775c0ed2fa451e578dd0594d13f11459e9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 20 Aug 2019 16:52:36 +1000 Subject: [PATCH 0426/1299] esp32: Add VFS FAT partition to partitions.csv and mount it as the FS. This patch uses the newly-added esp32.Partition class to replace the existing FlashBdev class. Partition objects implement the block protocol so can be directly mounted via uos.mount(). This has the following benefits: - allows the filesystem partition location and size to be specified in partitions.csv, and overridden by a particular board - very easily allows to have multiple filesystems by simply adding extra entries to partitions.csv - improves efficiency/speed of filesystem operations because the block device is implemented fully in C - opens the possibility to have encrypted flash storage (since Partitions can be encrypted) Note that this patch is fully backwards compatible: existing filesystems remain untouched and work with this new code. --- ports/esp32/modules/flashbdev.py | 36 +++----------------------------- ports/esp32/partitions.csv | 1 + 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/ports/esp32/modules/flashbdev.py b/ports/esp32/modules/flashbdev.py index 935f5342fcc25..45b8686c5505d 100644 --- a/ports/esp32/modules/flashbdev.py +++ b/ports/esp32/modules/flashbdev.py @@ -1,34 +1,4 @@ -import esp +from esp32 import Partition -class FlashBdev: - - SEC_SIZE = 4096 - START_SEC = esp.flash_user_start() // SEC_SIZE - - def __init__(self, blocks): - self.blocks = blocks - - def readblocks(self, n, buf): - #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) - esp.flash_read((n + self.START_SEC) * self.SEC_SIZE, buf) - - def writeblocks(self, n, buf): - #print("writeblocks(%s, %x(%d))" % (n, id(buf), len(buf))) - #assert len(buf) <= self.SEC_SIZE, len(buf) - esp.flash_erase(n + self.START_SEC) - esp.flash_write((n + self.START_SEC) * self.SEC_SIZE, buf) - - def ioctl(self, op, arg): - #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT - return self.blocks - if op == 5: # BP_IOCTL_SEC_SIZE - return self.SEC_SIZE - -size = esp.flash_size() -if size < 1024*1024: - # flash too small for a filesystem - bdev = None -else: - # for now we use a fixed size for the filesystem - bdev = FlashBdev(2048 * 1024 // FlashBdev.SEC_SIZE) +bdev = Partition.find(Partition.TYPE_DATA, label='vfs') +bdev = bdev[0] if bdev else None diff --git a/ports/esp32/partitions.csv b/ports/esp32/partitions.csv index 98adcd20a7037..55c225759edae 100644 --- a/ports/esp32/partitions.csv +++ b/ports/esp32/partitions.csv @@ -3,3 +3,4 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 0x180000, +vfs, data, fat, 0x200000, 0x200000, From 80d37d936c9832dc4b69ad631ad07697e26764d9 Mon Sep 17 00:00:00 2001 From: Alex Albino Date: Wed, 7 Aug 2019 07:22:15 -0700 Subject: [PATCH 0427/1299] esp32: Add support for ESP32-D2WD with 2MiB internal flash. This patch adds a partitions file for the D2WD and a new board GENERIC_D2WD which runs on these chip variants. Resolves issue #4986. --- ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h | 2 ++ ports/esp32/boards/GENERIC_D2WD/mpconfigboard.mk | 5 +++++ ports/esp32/partitions-2MiB.csv | 6 ++++++ 3 files changed, 13 insertions(+) create mode 100644 ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h create mode 100644 ports/esp32/boards/GENERIC_D2WD/mpconfigboard.mk create mode 100644 ports/esp32/partitions-2MiB.csv diff --git a/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h b/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h new file mode 100644 index 0000000000000..8923d46fd1569 --- /dev/null +++ b/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "Generic ESP32-D2WD module" +#define MICROPY_HW_MCU_NAME "ESP32-D2WD" diff --git a/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.mk b/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.mk new file mode 100644 index 0000000000000..65de5dcd08e55 --- /dev/null +++ b/ports/esp32/boards/GENERIC_D2WD/mpconfigboard.mk @@ -0,0 +1,5 @@ +SDKCONFIG += boards/sdkconfig.base +PART_SRC = partitions-2MiB.csv +FLASH_SIZE = 2MB +FLASH_MODE = dio +FLASH_FREQ = 40m diff --git a/ports/esp32/partitions-2MiB.csv b/ports/esp32/partitions-2MiB.csv new file mode 100644 index 0000000000000..84bc53782d37e --- /dev/null +++ b/ports/esp32/partitions-2MiB.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 0x110000, +vfs, data, fat, 0x120000, 0xA0000, From bd1d27f00f43bb44fca806cd0c53fa7196a1ea04 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 22:41:50 +1000 Subject: [PATCH 0428/1299] esp32/modules/inisetup.py: Use bdev.ioctl instead of bdev.SEC_SIZE. Since the bdev is now a Partition it doesn't have SEC_SIZE. --- ports/esp32/modules/inisetup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/modules/inisetup.py b/ports/esp32/modules/inisetup.py index 00d9a4eab82e8..3196f0c6f3eb6 100644 --- a/ports/esp32/modules/inisetup.py +++ b/ports/esp32/modules/inisetup.py @@ -2,7 +2,7 @@ from flashbdev import bdev def check_bootsec(): - buf = bytearray(bdev.SEC_SIZE) + buf = bytearray(bdev.ioctl(5, 0)) # 5 is SEC_SIZE bdev.readblocks(0, buf) empty = True for b in buf: From c8c37ca4076f72b79d5ec65c22a3e3bc0c71f583 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 10 Sep 2019 21:31:53 +1000 Subject: [PATCH 0429/1299] stm32/boards/STM32F769DISC: Fix number of SDRAM row bits. According to the schematic, the SDRAM part on this board is a MT48LC4M32B2B5-6A, with "Row addressing 4K A[11:0]" (per datasheet). This commit updates mpconfigboard.h from 13 to 12 to match. --- ports/stm32/boards/STM32F769DISC/mpconfigboard.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/STM32F769DISC/mpconfigboard.h b/ports/stm32/boards/STM32F769DISC/mpconfigboard.h index 9a700d8e42a55..a34b58e1b2992 100644 --- a/ports/stm32/boards/STM32F769DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F769DISC/mpconfigboard.h @@ -100,7 +100,14 @@ void board_early_init(void); #define MICROPY_HW_ETH_RMII_TXD1 (pin_G14) #if 0 -// Optional SDRAM configuration; requires SYSCLK <= 200MHz +// Optional SDRAM configuration. + +// Note: This requires SYSCLK <= 200MHz. 192MHz example below: +// #define MICROPY_HW_CLK_PLLM (25) +// #define MICROPY_HW_CLK_PLLN (384) +// #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +// #define MICROPY_HW_CLK_PLLQ (8) + #define MICROPY_HW_SDRAM_SIZE (128 * 1024 * 1024 / 8) // 128 Mbit #define MICROPY_HW_SDRAM_STARTUP_TEST (0) #define MICROPY_HEAP_START sdram_start() @@ -119,7 +126,7 @@ void board_early_init(void); #define MICROPY_HW_SDRAM_BURST_LENGTH 1 #define MICROPY_HW_SDRAM_CAS_LATENCY 2 #define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8 -#define MICROPY_HW_SDRAM_ROW_BITS_NUM 13 +#define MICROPY_HW_SDRAM_ROW_BITS_NUM 12 #define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 32 #define MICROPY_HW_SDRAM_INTERN_BANKS_NUM 4 #define MICROPY_HW_SDRAM_CLOCK_PERIOD 2 From cfec0540732b6ce3e21d3a81f088dc6a328ff4d7 Mon Sep 17 00:00:00 2001 From: cristian Date: Fri, 6 Sep 2019 15:50:24 -0500 Subject: [PATCH 0430/1299] stm32/board/NUCLEO_F746ZG: Enable Ethernet periph, lwip and ussl. --- ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h | 11 +++++++++++ ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk | 5 +++++ ports/stm32/boards/NUCLEO_F746ZG/pins.csv | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h index a9fbea5766c02..c9b0c60f274b0 100644 --- a/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.h @@ -75,3 +75,14 @@ #define MICROPY_HW_USB_FS (1) #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) + +// Ethernet via RMII +#define MICROPY_HW_ETH_MDC (pin_C1) +#define MICROPY_HW_ETH_MDIO (pin_A2) +#define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) +#define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) +#define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) +#define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) +#define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) +#define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) +#define MICROPY_HW_ETH_RMII_TXD1 (pin_B13) diff --git a/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk index 160218fd338aa..8b54dc84e113e 100644 --- a/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk @@ -4,3 +4,8 @@ AF_FILE = boards/stm32f746_af.csv LD_FILES = boards/stm32f746.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 + +# MicroPython settings +MICROPY_PY_LWIP = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 diff --git a/ports/stm32/boards/NUCLEO_F746ZG/pins.csv b/ports/stm32/boards/NUCLEO_F746ZG/pins.csv index aa5143e8c5ac1..c129f7417b595 100644 --- a/ports/stm32/boards/NUCLEO_F746ZG/pins.csv +++ b/ports/stm32/boards/NUCLEO_F746ZG/pins.csv @@ -66,3 +66,12 @@ UART6_RX,PG9 SPI_B_NSS,PA4 SPI_B_SCK,PB3 SPI_B_MOSI,PB5 +ETH_MDC,PC1 +ETH_MDIO,PA2 +ETH_RMII_REF_CLK,PA1 +ETH_RMII_CRS_DV,PA7 +ETH_RMII_RXD0,PC4 +ETH_RMII_RXD1,PC5 +ETH_RMII_TX_EN,PG11 +ETH_RMII_TXD0,PG13 +ETH_RMII_TXD1,PB13 From 6705767da1f7dba7a04e1d16c380a650f1f1074f Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 6 Jul 2019 00:19:45 +1000 Subject: [PATCH 0431/1299] stm32/usb: Add support for VCP+MSC+HID mode, incl 2xVCP and 3xVCP. --- ports/stm32/usb.c | 56 +++++++++++++- ports/stm32/usb.h | 3 + ports/stm32/usbd_conf.h | 2 +- .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 14 +--- .../usbdev/class/inc/usbd_cdc_msc_hid0.h | 3 + .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 75 ++++++++++++++++++- 6 files changed, 137 insertions(+), 16 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 791a6472a5a40..8b8062981561a 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -97,6 +97,14 @@ STATIC const uint8_t usbd_fifo_size_cdc1[] = { #endif }; +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, HID +STATIC const uint8_t usbd_fifo_size_cdc1_msc_hid[] = { + 32, 8, 16, 4, 12, 8, 0, + #if MICROPY_HW_USB_HS + 116, 8, 64, 4, 56, 8, 0, 0, 0, 0, + #endif +}; + #if MICROPY_HW_USB_CDC_NUM >= 2 // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA STATIC const uint8_t usbd_fifo_size_cdc2[] = { @@ -105,6 +113,14 @@ STATIC const uint8_t usbd_fifo_size_cdc2[] = { 116, 8, 64, 2, 32, 2, 32, 0, 0, 0, #endif }; + +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD/HID, CDC2_DATA, HID +STATIC const uint8_t usbd_fifo_size_cdc2_msc_hid[] = { + 0, 0, 0, 0, 0, 0, 0, // FS: can't support 2xVCP+MSC+HID + #if MICROPY_HW_USB_HS + 102, 8, 64, 2, 32, 8, 32, 8, 0, 0, + #endif +}; #endif #if MICROPY_HW_USB_CDC_NUM >= 3 @@ -115,6 +131,14 @@ STATIC const uint8_t usbd_fifo_size_cdc3[] = { 82, 8, 64, 2, 32, 2, 32, 2, 32, 0, #endif }; + +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD/HID, CDC2_DATA, CDC3_CMD/HID, CDC3_DATA, HID +STATIC const uint8_t usbd_fifo_size_cdc3_msc_hid[] = { + 0, 0, 0, 0, 0, 0, 0, // FS: can't support 3x VCP mode + #if MICROPY_HW_USB_HS + 82, 8, 64, 2, 25, 8, 25, 8, 25, 8, + #endif +}; #endif #endif @@ -242,14 +266,27 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size #endif const uint8_t *fifo_size = usbd_fifo_size_cdc1; + #if MICROPY_HW_USB_IS_MULTI_OTG + if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { + fifo_size = usbd_fifo_size_cdc1_msc_hid; + } + #endif #if MICROPY_HW_USB_CDC_NUM >= 3 if (mode & USBD_MODE_IFACE_CDC(2)) { - fifo_size = usbd_fifo_size_cdc3; + if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { + fifo_size = usbd_fifo_size_cdc3_msc_hid; + } else { + fifo_size = usbd_fifo_size_cdc3; + } } else #endif #if MICROPY_HW_USB_CDC_NUM >= 2 if (mode & USBD_MODE_IFACE_CDC(1)) { - fifo_size = usbd_fifo_size_cdc2; + if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { + fifo_size = usbd_fifo_size_cdc2_msc_hid; + } else { + fifo_size = usbd_fifo_size_cdc2; + } } #endif @@ -414,6 +451,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pid = USBD_PID_CDC_MSC; } mode = USBD_MODE_CDC_MSC; + } else if (strcmp(mode_str, "VCP+MSC+HID") == 0) { + if (pid == -1) { + pid = USBD_PID_CDC_MSC_HID; + } + mode = USBD_MODE_CDC_MSC_HID; #if MICROPY_HW_USB_CDC_NUM >= 2 } else if (strcmp(mode_str, "VCP+VCP") == 0) { if (pid == -1) { @@ -425,6 +467,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pid = USBD_PID_CDC2_MSC; } mode = USBD_MODE_CDC2_MSC; + } else if (strcmp(mode_str, "2xVCP+MSC+HID") == 0) { + if (pid == -1) { + pid = USBD_PID_CDC2_MSC_HID; + } + mode = USBD_MODE_CDC2_MSC_HID; #endif #if MICROPY_HW_USB_CDC_NUM >= 3 } else if (strcmp(mode_str, "3xVCP") == 0) { @@ -437,6 +484,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pid = USBD_PID_CDC3_MSC; } mode = USBD_MODE_CDC3_MSC; + } else if (strcmp(mode_str, "3xVCP+MSC+HID") == 0) { + if (pid == -1) { + pid = USBD_PID_CDC3_MSC_HID; + } + mode = USBD_MODE_CDC3_MSC_HID; #endif } else if (strcmp(mode_str, "CDC+HID") == 0 || strcmp(mode_str, "VCP+HID") == 0) { if (pid == -1) { diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index cb017902ecb50..457c7313c4d5a 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -40,6 +40,9 @@ #define USBD_PID_CDC2 (0x9805) #define USBD_PID_CDC3 (0x9806) #define USBD_PID_CDC3_MSC (0x9807) +#define USBD_PID_CDC_MSC_HID (0x9808) +#define USBD_PID_CDC2_MSC_HID (0x9809) +#define USBD_PID_CDC3_MSC_HID (0x980a) typedef enum { PYB_USB_STORAGE_MEDIUM_NONE = 0, diff --git a/ports/stm32/usbd_conf.h b/ports/stm32/usbd_conf.h index 83629bfc4f766..5237ba3a96e72 100644 --- a/ports/stm32/usbd_conf.h +++ b/ports/stm32/usbd_conf.h @@ -39,7 +39,7 @@ #include "py/mpconfig.h" -#define USBD_MAX_NUM_INTERFACES 5 +#define USBD_MAX_NUM_INTERFACES 8 #define USBD_MAX_NUM_CONFIGURATION 1 #define USBD_MAX_STR_DESC_SIZ 0x100 #if MICROPY_HW_USB_SELF_POWERED diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index a01e75bed5e21..f3edc4dcb4094 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -18,16 +18,8 @@ #endif // Should be maximum of possible config descriptors that might be configured -#if MICROPY_HW_USB_CDC_NUM == 3 -// Maximum is MSC+CDC+CDC+CDC -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58) + (8 + 58)) -#elif MICROPY_HW_USB_CDC_NUM == 2 -// Maximum is MSC+CDC+CDC -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58)) -#else -// Maximum is HID+CDC -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 32 + (8 + 58)) -#endif +// Maximum is: 9 + MSC + NxCDC + HID +#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + (23) + MICROPY_HW_USB_CDC_NUM * (8 + 58) + (9 + 9 + 7 + 7)) // CDC, MSC and HID packet sizes #define MSC_FS_MAX_PACKET (64) @@ -118,7 +110,7 @@ typedef struct _usbd_cdc_msc_hid_state_t { USBD_HandleTypeDef *pdev; uint8_t usbd_mode; - uint8_t usbd_config_desc_size; + uint16_t usbd_config_desc_size; #if MICROPY_HW_USB_MSC USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData; diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h index 63fe8ecefc77f..7614dde691fe1 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h @@ -44,6 +44,9 @@ #define USBD_MODE_CDC_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC) #define USBD_MODE_CDC2_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC) #define USBD_MODE_CDC3_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2) | USBD_MODE_IFACE_MSC) +#define USBD_MODE_CDC_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) +#define USBD_MODE_CDC2_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) +#define USBD_MODE_CDC3_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) #define USBD_MODE_HID (USBD_MODE_IFACE_HID) #define USBD_MODE_MSC (USBD_MODE_IFACE_MSC) #define USBD_MODE_MSC_HID (USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index e13a93ddbc9e1..938c8e711536e 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -61,9 +61,11 @@ #define HID_DESC_OFFSET_PROTOCOL (7) #define HID_DESC_OFFSET_SUBDESC (9) #define HID_DESC_OFFSET_REPORT_DESC_LEN (16) +#define HID_DESC_OFFSET_IN_EP (20) #define HID_DESC_OFFSET_MAX_PACKET_LO (22) #define HID_DESC_OFFSET_MAX_PACKET_HI (23) #define HID_DESC_OFFSET_POLLING_INTERVAL (24) +#define HID_DESC_OFFSET_OUT_EP (27) #define HID_DESC_OFFSET_MAX_PACKET_OUT_LO (29) #define HID_DESC_OFFSET_MAX_PACKET_OUT_HI (30) #define HID_DESC_OFFSET_POLLING_INTERVAL_OUT (31) @@ -79,6 +81,9 @@ #define MSC_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_MSC (1) +#define HID_IFACE_NUM_WITH_CDC_MSC (3) +#define HID_IFACE_NUM_WITH_CDC2_MSC (5) +#define HID_IFACE_NUM_WITH_CDC3_MSC (7) #define CDC_IN_EP(i) (0x83 + 2 * (i)) #define CDC_OUT_EP(i) (0x03 + 2 * (i)) @@ -88,6 +93,12 @@ #define HID_OUT_EP_WITH_CDC (0x01) #define HID_IN_EP_WITH_MSC (0x83) #define HID_OUT_EP_WITH_MSC (0x03) +#define HID_IN_EP_WITH_CDC_MSC (0x84) +#define HID_OUT_EP_WITH_CDC_MSC (0x04) +#define HID_IN_EP_WITH_CDC2_MSC (0x86) +#define HID_OUT_EP_WITH_CDC2_MSC (0x06) +#define HID_IN_EP_WITH_CDC3_MSC (0x88) +#define HID_OUT_EP_WITH_CDC3_MSC (0x08) #define USB_DESC_TYPE_ASSOCIATION (0x0b) @@ -448,8 +459,9 @@ static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, u #endif #if MICROPY_HW_USB_HID -static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info) { +static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t iface_num) { memcpy(dest, hid_class_desc_data, sizeof(hid_class_desc_data)); + dest[2] = iface_num; dest[HID_DESC_OFFSET_SUBCLASS] = hid_info->subclass; dest[HID_DESC_OFFSET_PROTOCOL] = hid_info->protocol; dest[HID_DESC_OFFSET_REPORT_DESC_LEN] = hid_info->report_desc_len; @@ -461,6 +473,15 @@ static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info) { dest[HID_DESC_OFFSET_POLLING_INTERVAL_OUT] = hid_info->polling_interval; return sizeof(hid_class_desc_data); } + +#if MICROPY_HW_USB_MSC +static size_t make_hid_desc_ep(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t iface_num, uint8_t in_ep, uint8_t out_ep) { + size_t n = make_hid_desc(dest, hid_info, iface_num); + dest[HID_DESC_OFFSET_IN_EP] = in_ep; + dest[HID_DESC_OFFSET_OUT_EP] = out_ep; + return n; +} +#endif #endif // return the saved usb mode @@ -489,6 +510,21 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; num_itf = 3; break; + + #if MICROPY_HW_USB_HID + case USBD_MODE_CDC_MSC_HID: + n += make_msc_desc(d + n); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); + usbd->hid->desc = d + n; + n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC_MSC, HID_IN_EP_WITH_CDC_MSC, HID_OUT_EP_WITH_CDC_MSC); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->hid->in_ep = HID_IN_EP_WITH_CDC_MSC; + usbd->hid->out_ep = HID_OUT_EP_WITH_CDC_MSC; + usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC_MSC; + usbd->hid->report_desc = hid_info->report_desc; + num_itf = 4; + break; + #endif #endif #if MICROPY_HW_USB_CDC_NUM >= 2 @@ -511,6 +547,23 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode num_itf = 5; break; } + + case USBD_MODE_CDC2_MSC_HID: { + n += make_msc_desc(d + n); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + usbd->hid->desc = d + n; + n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC2_MSC, HID_IN_EP_WITH_CDC2_MSC, HID_OUT_EP_WITH_CDC2_MSC); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; + usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; + usbd->hid->in_ep = HID_IN_EP_WITH_CDC2_MSC; + usbd->hid->out_ep = HID_OUT_EP_WITH_CDC2_MSC; + usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC2_MSC; + usbd->hid->report_desc = hid_info->report_desc; + num_itf = 6; + break; + } #endif #endif @@ -538,13 +591,31 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode num_itf = 7; break; } + + case USBD_MODE_CDC3_MSC_HID: { + n += make_msc_desc(d + n); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + n += make_cdc_desc_ep(d + n, 1, CDC3_IFACE_NUM_WITH_MSC, CDC_CMD_EP(2), CDC_OUT_EP(2), CDC_IN_EP(2)); + usbd->hid->desc = d + n; + n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC3_MSC, HID_IN_EP_WITH_CDC3_MSC, HID_OUT_EP_WITH_CDC3_MSC); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; + usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; + usbd->hid->in_ep = HID_IN_EP_WITH_CDC3_MSC; + usbd->hid->out_ep = HID_OUT_EP_WITH_CDC3_MSC; + usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC3_MSC; + usbd->hid->report_desc = hid_info->report_desc; + num_itf = 8; + break; + } #endif #endif #if MICROPY_HW_USB_HID case USBD_MODE_CDC_HID: usbd->hid->desc = d + n; - n += make_hid_desc(d + n, hid_info); + n += make_hid_desc(d + n, hid_info, HID_IFACE_NUM_WITH_CDC); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_HID; usbd->hid->in_ep = HID_IN_EP_WITH_CDC; From bcaafa382323c5d15988f20782c2737f05a4c002 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 11 Sep 2019 14:59:02 +1000 Subject: [PATCH 0432/1299] stm32/usb: Verify number of used endpoints doesn't exceed maximum. --- ports/stm32/usb.c | 15 ++++++++++++++- ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 2 +- ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 13 ++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8b8062981561a..ca5cc682ec488 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -57,6 +57,19 @@ #endif #endif +// Maximum number of endpoints (excluding EP0) +#if defined(STM32L0) || defined(STM32WB) +#define MAX_ENDPOINT(dev_id) (7) +#elif defined(STM32L4) +#define MAX_ENDPOINT(dev_id) (5) +#elif defined(STM32F4) +#define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 3 : 5) +#elif defined(STM32F7) +#define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 5 : 8) +#elif defined(STM32H7) +#define MAX_ENDPOINT(dev_id) (8) +#endif + STATIC void pyb_usb_vcp_init0(void); // this will be persistent across a soft-reset @@ -240,7 +253,7 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size // configure the VID, PID and the USBD mode (interfaces it will expose) int cdc_only = (mode & USBD_MODE_IFACE_MASK) == USBD_MODE_CDC; USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, cdc_only); - if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info) != 0) { + if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info, MAX_ENDPOINT(dev_id)) != 0) { return false; } diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index f3edc4dcb4094..d934f4676c4df 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -165,7 +165,7 @@ static inline uint32_t usbd_cdc_max_packet(USBD_HandleTypeDef *pdev) { } // returns 0 on success, -1 on failure -int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info); +int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t max_endpoint); // returns the current usb mode uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd); diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 938c8e711536e..0b9407654320d 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -489,7 +489,7 @@ uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd) { return usbd->usbd_mode; } -int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { +int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t max_endpoint) { // save mode usbd->usbd_mode = mode; @@ -656,6 +656,17 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode } } + // Verify that the endpoints that are used fit within the maximum number + d = usbd->usbd_config_desc; + const uint8_t *d_top = d + n; + while (d < d_top) { + if (d[0] == 7 && d[1] == USB_DESC_TYPE_ENDPOINT && (d[2] & 0x7f) > max_endpoint) { + // Endpoint out of range of hardware + return -1; + } + d += d[0]; + } + return 0; } From cb84e22ac6b1356986f63f5b6db95493da81fa5f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 11 Sep 2019 15:16:19 +1000 Subject: [PATCH 0433/1299] docs/library/pyb.rst: Update pyb.usb_mode() to mention VCP+MSC+HID. --- docs/library/pyb.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst index acb8fe450efd6..9ba7e991e5190 100644 --- a/docs/library/pyb.rst +++ b/docs/library/pyb.rst @@ -271,6 +271,7 @@ Miscellaneous functions - ``'MSC'``: enable with MSC (mass storage device class) interface - ``'VCP+MSC'``: enable with VCP and MSC - ``'VCP+HID'``: enable with VCP and HID (human interface device) + - ``'VCP+MSC+HID'``: enabled with VCP, MSC and HID (only available on PYBD boards) For backwards compatibility, ``'CDC'`` is understood to mean ``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``). From b0e17bbb9d804b04a566b809c19acd5128f972e5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Sep 2019 18:05:27 +1000 Subject: [PATCH 0434/1299] stm32/lwip_inc: Allocate additional MEMP_SYS_TIMEOUT when mDNS enabled. Since v2.1 of lwIP mDNS uses a MEMP_SYS_TIMEOUT slot, so allocate an extra one when this feature is enabled. --- ports/stm32/lwip_inc/lwipopts.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/stm32/lwip_inc/lwipopts.h b/ports/stm32/lwip_inc/lwipopts.h index c9bbde92f723b..4ad1ae0083318 100644 --- a/ports/stm32/lwip_inc/lwipopts.h +++ b/ports/stm32/lwip_inc/lwipopts.h @@ -32,8 +32,9 @@ #define LWIP_MDNS_RESPONDER 1 #define LWIP_IGMP 1 -#define LWIP_NUM_NETIF_CLIENT_DATA 1 // mDNS responder requires 1 -#define MEMP_NUM_UDP_PCB 5 // mDNS responder requires 1 +#define LWIP_NUM_NETIF_CLIENT_DATA LWIP_MDNS_RESPONDER +#define MEMP_NUM_UDP_PCB (4 + LWIP_MDNS_RESPONDER) +#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + LWIP_MDNS_RESPONDER) #define SO_REUSE 1 #define TCP_LISTEN_BACKLOG 1 From f66616556db608d8ca89889340283c532d5c4da0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Sep 2019 18:08:50 +1000 Subject: [PATCH 0435/1299] stm32/lwip_inc: Enable LWIP_NETIF_EXT_STATUS_CALLBACK for mDNS. This feature makes sure that mDNS is automatically restarted when there is any change event on a netif. --- ports/stm32/lwip_inc/lwipopts.h | 1 + ports/stm32/modnetwork.c | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/ports/stm32/lwip_inc/lwipopts.h b/ports/stm32/lwip_inc/lwipopts.h index 4ad1ae0083318..7b2460fa80aaa 100644 --- a/ports/stm32/lwip_inc/lwipopts.h +++ b/ports/stm32/lwip_inc/lwipopts.h @@ -22,6 +22,7 @@ #define LWIP_SOCKET 0 #define LWIP_STATS 0 #define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETIF_EXT_STATUS_CALLBACK 1 #define LWIP_IPV6 0 #define LWIP_DHCP 1 diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index 80e5a5a16257a..13ecf444f0c5f 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -189,10 +189,6 @@ mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_o mp_hal_delay_ms(100); } - #if LWIP_MDNS_RESPONDER - mdns_resp_netif_settings_changed(netif); - #endif - return mp_const_none; } else { // Release and stop any existing DHCP @@ -207,9 +203,6 @@ mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_o ip_addr_t dns; netutils_parse_ipv4_addr(items[3], (uint8_t*)&dns, NETUTILS_BIG); dns_setserver(0, &dns); - #if LWIP_MDNS_RESPONDER - mdns_resp_netif_settings_changed(netif); - #endif return mp_const_none; } } From 6e07fde895ba84281f2e3efd82145a4e1b8a4a1d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 11 Sep 2019 15:47:52 +1000 Subject: [PATCH 0436/1299] py/mkrules.mk: Add QSTR_GLOBAL_REQUIREMENTS variable for qstr auto-gen. --- py/mkrules.mk | 2 +- py/py.mk | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/py/mkrules.mk b/py/mkrules.mk index 7690c54092501..b74dd4549528a 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -70,7 +70,7 @@ $(OBJ): | $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/mpversion.h # - if anything in QSTR_GLOBAL_DEPENDENCIES is newer, then process all source files ($^) # - else, if list of newer prerequisites ($?) is not empty, then process just these ($?) # - else, process all source files ($^) [this covers "make -B" which can set $? to empty] -$(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h +$(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(QSTR_GLOBAL_REQUIREMENTS) $(ECHO) "GEN $@" $(Q)$(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) >$(HEADER_BUILD)/qstr.i.last diff --git a/py/py.mk b/py/py.mk index d60e694ec21fb..a3d9e790fc783 100644 --- a/py/py.mk +++ b/py/py.mk @@ -13,8 +13,10 @@ ifneq ($(QSTR_AUTOGEN_DISABLE),1) QSTR_DEFS_COLLECTED = $(HEADER_BUILD)/qstrdefs.collected.h endif -# Any files listed by this variable will cause a full regeneration of qstrs +# Any files listed by these variables will cause a full regeneration of qstrs +# DEPENDENCIES: included in qstr processing; REQUIREMENTS: not included QSTR_GLOBAL_DEPENDENCIES += $(PY_SRC)/mpconfig.h mpconfigport.h +QSTR_GLOBAL_REQUIREMENTS += $(HEADER_BUILD)/mpversion.h # some code is performance bottleneck and compiled with other optimization options CSUPEROPT = -O3 From 356a728bd0819de503c892a8f1ba55d0bea43a23 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 11 Sep 2019 15:49:24 +1000 Subject: [PATCH 0437/1299] esp32/Makefile: Add SDKCONFIG_H to QSTR_GLOBAL_REQUIREMENTS. Fixes issue #5091. --- ports/esp32/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 1e0298452010f..3e48febf0e030 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -25,6 +25,7 @@ include $(BOARD_DIR)/mpconfigboard.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h +QSTR_GLOBAL_REQUIREMENTS = $(SDKCONFIG_H) MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 From 22099ab88fe054c41090634d096fef7949af2971 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Sep 2019 19:10:12 +1000 Subject: [PATCH 0438/1299] stm32/machine_adc: Fix build for F4 and L4 MCUs that only have ADC1. --- ports/stm32/machine_adc.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 416beeca4cb4f..3aacae77babef 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -33,6 +33,12 @@ #define ADC_V2 (0) #endif +#if defined(STM32F4) || defined(STM32L4) +#define ADCx_COMMON ADC_COMMON_REGISTER(0) +#elif defined(STM32F7) +#define ADCx_COMMON ADC123_COMMON +#endif + #if defined(STM32F0) || defined(STM32L0) #define ADC_STAB_DELAY_US (1) #define ADC_TEMPSENSOR_DELAY_US (10) @@ -122,7 +128,7 @@ STATIC void adc_config(ADC_TypeDef *adc, uint32_t bits) { #if defined(STM32F0) adc->CFGR2 = 1 << ADC_CFGR2_CKMODE_Pos; // PCLK/2 (synchronous clock mode) #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L4) - ADC123_COMMON->CCR = 0; // ADCPR=PCLK/2 + ADCx_COMMON->CCR = 0; // ADCPR=PCLK/2 #elif defined(STM32H7) ADC12_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; ADC3_COMMON->CCR = 3 << ADC_CCR_CKMODE_Pos; @@ -255,12 +261,12 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp #elif defined(STM32F4) || defined(STM32F7) if (channel == ADC_CHANNEL_VREFINT || channel == ADC_CHANNEL_TEMPSENSOR) { - ADC123_COMMON->CCR = (ADC123_COMMON->CCR & ~ADC_CCR_VBATE) | ADC_CCR_TSVREFE; + ADCx_COMMON->CCR = (ADCx_COMMON->CCR & ~ADC_CCR_VBATE) | ADC_CCR_TSVREFE; if (channel == ADC_CHANNEL_TEMPSENSOR) { adc_stabilisation_delay_us(ADC_TEMPSENSOR_DELAY_US); } } else if (channel == ADC_CHANNEL_VBAT) { - ADC123_COMMON->CCR |= ADC_CCR_VBATE; + ADCx_COMMON->CCR |= ADC_CCR_VBATE; } adc->SQR3 = (channel & 0x1f) << ADC_SQR3_SQ1_Pos; // select channel for first conversion @@ -280,7 +286,7 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp adc->PCSEL |= 1 << channel; ADC_Common_TypeDef *adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON; #elif defined(STM32L4) - ADC_Common_TypeDef *adc_common = ADC123_COMMON; + ADC_Common_TypeDef *adc_common = ADCx_COMMON; #elif defined(STM32WB) ADC_Common_TypeDef *adc_common = ADC1_COMMON; #endif @@ -348,16 +354,17 @@ typedef struct _machine_adc_obj_t { STATIC void machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in); - #if defined(STM32F0) || defined(STM32L0) || defined(STM32WB) unsigned adc_id = 1; - #else - unsigned adc_id = (self->adc - ADC1) / (ADC2 - ADC1) + 1; - #if defined(STM32H7) + #if defined(ADC2) + if (self->adc == ADC2) { + adc_id = 2; + } + #endif + #if defined(ADC3) if (self->adc == ADC3) { adc_id = 3; } #endif - #endif mp_printf(print, "", adc_id, self->channel); } From ac112f88d0496d33a9195ace02ed3928fcb015d3 Mon Sep 17 00:00:00 2001 From: roland van straten Date: Tue, 10 Sep 2019 23:01:27 +0200 Subject: [PATCH 0439/1299] nrf/boards: Add board definition for uBlox Nina B1 series BLE modules. --- ports/nrf/README.md | 2 + ports/nrf/boards/evk_nina_b1/mpconfigboard.h | 72 +++++++++++++++++++ ports/nrf/boards/evk_nina_b1/mpconfigboard.mk | 7 ++ ports/nrf/boards/evk_nina_b1/pins.csv | 41 +++++++++++ 4 files changed, 122 insertions(+) create mode 100644 ports/nrf/boards/evk_nina_b1/mpconfigboard.h create mode 100644 ports/nrf/boards/evk_nina_b1/mpconfigboard.mk create mode 100644 ports/nrf/boards/evk_nina_b1/pins.csv diff --git a/ports/nrf/README.md b/ports/nrf/README.md index df5904eb610fd..49642f00e9e61 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -36,6 +36,7 @@ This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. * [Arduino Primo](http://www.arduino.org/products/boards/arduino-primo) * [IBK-BLYST-NANO breakout board](https://www.crowdsupply.com/i-syst/blyst-nano) * [BLUEIO-TAG-EVIM BLYST Nano Sensor board](https://www.crowdsupply.com/i-syst/blyst-nano) + * [uBlox EVK-NINA-B1](https://www.u-blox.com/en/product/evk-nina-b1) * nRF52840 * [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK) * [Particle Xenon](https://docs.particle.io/xenon/) @@ -126,6 +127,7 @@ arduino_primo | s132 | Peripheral and Central | [PyOCD ibk_blyst_nano | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) idk_blyst_nano | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) blueio_tag_evim | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) +evk_nina_b1 | s132 | Peripheral and Central | [Segger](#segger-targets) pca10056 | s140 | Peripheral and Central | [Segger](#segger-targets) particle_xenon | s140 | Peripheral and Central | [Black Magic Probe](#black-magic-probe-targets) diff --git a/ports/nrf/boards/evk_nina_b1/mpconfigboard.h b/ports/nrf/boards/evk_nina_b1/mpconfigboard.h new file mode 100644 index 0000000000000..ced6b8cb1f6fc --- /dev/null +++ b/ports/nrf/boards/evk_nina_b1/mpconfigboard.h @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Roland van Straten + * + * 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. + */ + +// Datasheet for board: +// https://www.u-blox.com/sites/default/files/EVK-NINA-B1_UserGuide_%28UBX-15028120%29.pdf +#define MICROPY_HW_BOARD_NAME "EVK_NINA_B1" +#define MICROPY_HW_MCU_NAME "NRF52832" +#define MICROPY_PY_SYS_PLATFORM "nrf52" + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_RTCOUNTER (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_TEMP (1) +#define MICROPY_PY_RANDOM_HW_RNG (1) + +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_LED_TRICOLOR (1) +#define MICROPY_HW_LED_PULLUP (1) + +#define MICROPY_HW_LED_RED (8) // LED1 DS8 Red +#define MICROPY_HW_LED_GREEN (16) // LED2 DS8 Green +#define MICROPY_HW_LED_BLUE (18) // LED3 DS8 Blue +// LEDs conflict with UART +//#define MICROPY_HW_LED4 (7) // DS1 Green +//#define MICROPY_HW_LED5 (31) // DS2 Orange +//#define MICROPY_HW_LED6 (5) // DS7 Green +//#define MICROPY_HW_LED7 (6) // DS8 Orange + +// UART config +#define MICROPY_HW_UART1_RX (5) +#define MICROPY_HW_UART1_TX (6) +#define MICROPY_HW_UART1_CTS (7) +#define MICROPY_HW_UART1_RTS (31) +#define MICROPY_HW_UART1_HWFC (1) + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" +#define MICROPY_HW_SPI0_SCK (14) +#define MICROPY_HW_SPI0_MOSI (13) +#define MICROPY_HW_SPI0_MISO (12) + +#define MICROPY_HW_PWM0_NAME "PWM0" +#define MICROPY_HW_PWM1_NAME "PWM1" +#define MICROPY_HW_PWM2_NAME "PWM2" + +#define HELP_TEXT_BOARD_LED "1,2,3" diff --git a/ports/nrf/boards/evk_nina_b1/mpconfigboard.mk b/ports/nrf/boards/evk_nina_b1/mpconfigboard.mk new file mode 100644 index 0000000000000..db64a60dd3685 --- /dev/null +++ b/ports/nrf/boards/evk_nina_b1/mpconfigboard.mk @@ -0,0 +1,7 @@ +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52832 +SOFTDEV_VERSION = 6.1.1 +LD_FILES += boards/nrf52832_512k_64k.ld + +NRF_DEFINES += -DNRF52832_XXAA diff --git a/ports/nrf/boards/evk_nina_b1/pins.csv b/ports/nrf/boards/evk_nina_b1/pins.csv new file mode 100644 index 0000000000000..876c7ddc1a904 --- /dev/null +++ b/ports/nrf/boards/evk_nina_b1/pins.csv @@ -0,0 +1,41 @@ +A0,P3,ADC0_IN1 +A1,P2,ADC0_IN0 +A2,P4,ADC0_IN2 +A3,P30,ADC0_IN6 +A4,P29,ADC0_IN5 +A5,P28,ADC0_IN4 +LED1,P8 +LED2,P16 +LED3,P18 +SW2,P30 +UART1_RX,P5 +UART1_TX,P6 +UART1_CTS,P7 +UART1_RTS,P8 +SDA,P2 +SCL,P3 +NFC1,P9 +NFC2,P10 +D0,P5 +D1,P6 +D2,P7 +D3,P31 +D4,P18 +D6,P9 +D7,P10 +D9,P8 +D10,P11 +D11,P13 +D12,P12 +D13,P14 +P15,P15 +P17,P17 +P19,P19 +P20,P20 +P21,P21 +P22,P22 +P23,P23 +P24,P24 +P25,P25 +P26,P26 +P27,P27 From b45f9de8096f37a5f588f833e6b6a00b59e67e3f Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Sep 2019 22:14:51 +1000 Subject: [PATCH 0440/1299] bare-arm, minimal: Set CSUPEROPT=-Os to get minimal firmware size. This option affects py/vm.c and py/gc.c and using -Os gets them compiling a bit smaller, and small firmware is the aim of these two ports. Also, having these files compiled with -Os on these ports, and -O3 as the default on other ports, gives a better understanding of code-size changes when making changes to these files. --- ports/bare-arm/Makefile | 1 + ports/minimal/Makefile | 2 ++ 2 files changed, 3 insertions(+) diff --git a/ports/bare-arm/Makefile b/ports/bare-arm/Makefile index a515db80e0aa2..7cb3432819193 100644 --- a/ports/bare-arm/Makefile +++ b/ports/bare-arm/Makefile @@ -14,6 +14,7 @@ INC += -I$(BUILD) CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT) +CSUPEROPT = -Os # save some code space #Debugging/Optimization ifeq ($(DEBUG), 1) diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index b3e27509f1671..f26a7ec97d5e7 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -28,6 +28,8 @@ CFLAGS = -m32 $(INC) -Wall -Werror -std=c99 $(COPT) LDFLAGS = -m32 -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif +CSUPEROPT = -Os # save some code space + # Tune for Debugging or Optimization ifeq ($(DEBUG), 1) CFLAGS += -O0 -ggdb From 96008ff59a8af9883af17d01b951029d9d02eec9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 13 Sep 2019 23:04:13 +1000 Subject: [PATCH 0441/1299] esp32: Support building with ESP IDF 4.0-beta1. This commit adds support for a second supported hash (currently set to the 4.0-beta1 tag). When this hash is detected, the relevant changes are applied. This allows to start using v4 features (e.g. BLE with Nimble), and also start doing testing, while still supporting the original, stable, v3.3 IDF. Note: this feature is experimental, not well tested, and network.LAN and network.PPP are currently unsupported. --- ports/esp32/Makefile | 198 +++++++++++++++++--- ports/esp32/boards/TINYPICO/sdkconfig.board | 1 + ports/esp32/boards/sdkconfig.base | 11 +- ports/esp32/boards/sdkconfig.spiram | 6 +- ports/esp32/esp32_ulp.c | 4 + ports/esp32/main.c | 12 +- ports/esp32/modesp.c | 2 + ports/esp32/modmachine.c | 6 + ports/esp32/modnetwork.c | 18 +- ports/esp32/modsocket.c | 48 +++-- ports/esp32/mpconfigport.h | 3 + ports/esp32/mphalport.c | 5 + ports/esp32/mpthreadport.c | 3 + ports/esp32/network_lan.c | 3 + ports/esp32/network_ppp.c | 3 + 15 files changed, 266 insertions(+), 57 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 3e48febf0e030..25001643eedc3 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -50,7 +50,13 @@ SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined SDKCONFIG_H = $(BUILD)/sdkconfig.h # the git hash of the currently supported ESP IDF version -ESPIDF_SUPHASH := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df +ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df +ESPIDF_SUPHASH_V4 := 310beae373446ceb9a4ad9b36b5428d7fdf2705f + +define print_supported_git_hash +$(info Supported git hash (v3.3): $(ESPIDF_SUPHASH_V3)) +$(info Supported git hash (v4.0-beta1) (experimental): $(ESPIDF_SUPHASH_V4)) +endef # paths to ESP IDF and its components ifeq ($(ESPIDF),) @@ -59,10 +65,11 @@ ESPIDF = $(IDF_PATH) else $(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) $(info See README.md for installation instructions.) -$(info Supported git hash: $(ESPIDF_SUPHASH)) $(error ESPIDF not set) +print_supported_git_hash endif endif + ESPCOMP = $(ESPIDF)/components ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py ESPCOMP_KCONFIGS = $(shell find $(ESPCOMP) -name Kconfig) @@ -70,13 +77,18 @@ ESPCOMP_KCONFIGS_PROJBUILD = $(shell find $(ESPCOMP) -name Kconfig.projbuild) # verify the ESP IDF version ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') -ifneq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH)) + +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) +$(info Building with ESP IDF v3) +else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +$(info Building with ESP IDF v4) +else $(info ** WARNING **) $(info The git hash of ESP IDF does not match the supported version) $(info The build may complete and the firmware may work but it is not guaranteed) $(info ESP IDF path: $(ESPIDF)) $(info Current git hash: $(ESPIDF_CURHASH)) -$(info Supported git hash: $(ESPIDF_SUPHASH)) +print_supported_git_hash endif # pretty format of ESP IDF version, used internally by the IDF @@ -100,20 +112,13 @@ INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader INC_ESPCOMP += -I$(ESPCOMP)/console INC_ESPCOMP += -I$(ESPCOMP)/driver/include INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver -INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include -INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes INC_ESPCOMP += -I$(ESPCOMP)/efuse/include INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include INC_ESPCOMP += -I$(ESPCOMP)/soc/include INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include -INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include -INC_ESPCOMP += -I$(ESPCOMP)/expat/expat/expat/lib -INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include INC_ESPCOMP += -I$(ESPCOMP)/heap/include -INC_ESPCOMP += -I$(ESPCOMP)/json/include -INC_ESPCOMP += -I$(ESPCOMP)/json/port/include INC_ESPCOMP += -I$(ESPCOMP)/log/include INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include INC_ESPCOMP += -I$(ESPCOMP)/newlib/include @@ -129,20 +134,41 @@ INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include INC_ESPCOMP += -I$(ESPCOMP)/mdns/include INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include -INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include INC_ESPCOMP += -I$(ESPCOMP)/ulp/include INC_ESPCOMP += -I$(ESPCOMP)/vfs/include INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include -INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include INC_ESPCOMP += -I$(ESPCOMP)/app_update/include INC_ESPCOMP += -I$(ESPCOMP)/pthread/include INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_eth/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_event/private_include +INC_ESPCOMP += -I$(ESPCOMP)/esp_rom/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps/sntp +INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/private_include +INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include/esp_supplicant +INC_ESPCOMP += -I$(ESPCOMP)/xtensa/include +INC_ESPCOMP += -I$(ESPCOMP)/xtensa/esp32/include +else +INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include +INC_ESPCOMP += -I$(ESPCOMP)/expat/expat/expat/lib +INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include +INC_ESPCOMP += -I$(ESPCOMP)/json/include +INC_ESPCOMP += -I$(ESPCOMP)/json/port/include +INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc +INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include +INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes +endif + # these flags are common to C and C++ compilation CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ -mlongcalls -nostdlib \ @@ -156,6 +182,10 @@ CFLAGS += -DIDF_VER=\"$(IDF_VER)\" CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -I$(BOARD_DIR) +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +CFLAGS += -DMICROPY_ESP_IDF_4=1 +endif + # this is what ESPIDF uses for c++ compilation CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP) @@ -164,6 +194,7 @@ LDFLAGS += --gc-sections -static -EL LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority -u ld_include_panic_highint_hdl LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a LDFLAGS += -L$(ESPCOMP)/esp32/ld +LDFLAGS += -L$(ESPCOMP)/esp_rom/esp32/ld LDFLAGS += -T $(BUILD)/esp32_out.ld LDFLAGS += -T $(BUILD)/esp32.project.ld LDFLAGS += -T esp32.rom.ld @@ -183,12 +214,19 @@ COPT += -Os -DNDEBUG #LDFLAGS += --gc-sections endif -# Enable SPIRAM support if CONFIG_SPIRAM_SUPPORT=y in sdkconfig -ifeq ($(CONFIG_SPIRAM_SUPPORT),y) +# Enable SPIRAM support if CONFIG_ESP32_SPIRAM_SUPPORT=y in sdkconfig +ifeq ($(CONFIG_ESP32_SPIRAM_SUPPORT),y) CFLAGS_COMMON += -mfix-esp32-psram-cache-issue LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc-psram-workaround.a $(ESPCOMP)/newlib/lib/libm-psram-workaround.a else +# Additional newlib symbols that can only be used with spiram disabled. +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +LDFLAGS += -T esp32.rom.newlib-funcs.ld +LDFLAGS += -T esp32.rom.newlib-locale.ld +LDFLAGS += -T esp32.rom.newlib-data.ld +else LDFLAGS += -T esp32.rom.spiram_incompatible_fns.ld +endif LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc.a $(ESPCOMP)/newlib/lib/libm.a endif @@ -283,7 +321,8 @@ $(SDKCONFIG_H): $(SDKCONFIG_COMBINED) --env "IDF_TARGET=esp32" \ --env "IDF_CMAKE=n" \ --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ - --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" + --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ + --env "IDF_PATH=$(ESPIDF)" $(Q)touch $@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard.h @@ -293,7 +332,9 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(SDKCONFIG_H) $(BOARD_DIR)/mpconfigboard. ESPIDF_BOOTLOADER_SUPPORT_O = $(patsubst %.c,%.o,\ $(filter-out $(ESPCOMP)/bootloader_support/src/bootloader_init.c,\ - $(wildcard $(ESPCOMP)/bootloader_support/src/*.c))) + $(wildcard $(ESPCOMP)/bootloader_support/src/*.c) \ + $(wildcard $(ESPCOMP)/bootloader_support/src/idf/*.c) \ + )) ESPIDF_DRIVER_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/driver/*.c)) @@ -315,22 +356,22 @@ ESPIDF_HEAP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/heap/*.c)) ESPIDF_SOC_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/soc/esp32/*.c) \ $(wildcard $(ESPCOMP)/soc/src/*.c) \ + $(wildcard $(ESPCOMP)/soc/src/hal/*.c) \ ) ESPIDF_CXX_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/cxx/*.cpp)) -ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ - $(wildcard $(ESPCOMP)/ethernet/*.c) \ - $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ - ) - ESPIDF_PTHREAD_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/pthread/*.c)) # Assembler .S files need only basic flags, and in particular should not have # -Os because that generates subtly different code. # We also need custom CFLAGS for .c files because FreeRTOS has headers with # generic names (eg queue.h) which can clash with other files in the port. +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. -I$(ESPCOMP)/xtensa/include -I$(ESPCOMP)/xtensa/esp32/include -I$(ESPCOMP)/esp_common/include +else CFLAGS_ASM = -I$(BUILD) -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I. +endif $(BUILD)/$(ESPCOMP)/freertos/portasm.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_context.o: CFLAGS = $(CFLAGS_ASM) $(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM) @@ -343,8 +384,6 @@ ESPIDF_FREERTOS_O = \ ESPIDF_VFS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/vfs/*.c)) -ESPIDF_JSON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/json/cJSON/cJSON*.c)) - ESPIDF_LOG_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/log/*.c)) ESPIDF_XTENSA_DEBUG_MODULE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/xtensa-debug-module/*.c)) @@ -382,11 +421,16 @@ ESPIDF_LWIP_O = $(patsubst %.c,%.o,\ ESPIDF_MBEDTLS_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/mbedtls/mbedtls/library/*.c) \ $(wildcard $(ESPCOMP)/mbedtls/port/*.c) \ + $(wildcard $(ESPCOMP)/mbedtls/port/esp32/*.c) \ ) ESPIDF_MDNS_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/mdns/*.c)) +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +$(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing -I$(ESPCOMP)/wpa_supplicant/src -Wno-implicit-function-declaration +else $(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DALLOW_EVEN_MOD -D__ets__ -Wno-strict-aliasing +endif ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/wpa_supplicant/port/*.c) \ $(wildcard $(ESPCOMP)/wpa_supplicant/src/*/*.c) \ @@ -394,6 +438,29 @@ ESPIDF_WPA_SUPPLICANT_O = $(patsubst %.c,%.o,\ ESPIDF_SDMMC_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/sdmmc/*.c)) +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +ESPIDF_ESP_COMMON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_common/src/*.c)) + +ESPIDF_ESP_EVENT_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_event/*.c)) + +ESPIDF_ESP_WIFI_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_wifi/src/*.c)) + +$(BUILD)/$(ESPCOMP)/esp_eth/src/esp_eth_mac_dm9051.o: CFLAGS += -fno-strict-aliasing +ESPIDF_ESP_ETH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_eth/src/*.c)) + +ESPIDF_XTENSA_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/xtensa/*.c) \ + $(wildcard $(ESPCOMP)/xtensa/esp32/*.c) \ + ) +else +ESPIDF_JSON_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/json/cJSON/cJSON*.c)) + +ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/ethernet/*.c) \ + $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ + ) +endif + OBJ_ESPIDF = LIB_ESPIDF = BUILD_ESPIDF_LIB = $(BUILD)/esp-idf @@ -414,7 +481,6 @@ $(eval $(call gen_espidf_lib_rule,esp_ringbuf,$(ESPIDF_ESP_RINGBUF_O))) $(eval $(call gen_espidf_lib_rule,heap,$(ESPIDF_HEAP_O))) $(eval $(call gen_espidf_lib_rule,soc,$(ESPIDF_SOC_O))) $(eval $(call gen_espidf_lib_rule,cxx,$(ESPIDF_CXX_O))) -$(eval $(call gen_espidf_lib_rule,ethernet,$(ESPIDF_ETHERNET_O))) $(eval $(call gen_espidf_lib_rule,pthread,$(ESPIDF_PTHREAD_O))) $(eval $(call gen_espidf_lib_rule,freertos,$(ESPIDF_FREERTOS_O))) $(eval $(call gen_espidf_lib_rule,vfs,$(ESPIDF_VFS_O))) @@ -435,6 +501,16 @@ $(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O))) $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +$(eval $(call gen_espidf_lib_rule,esp_common,$(ESPIDF_ESP_COMMON_O))) +$(eval $(call gen_espidf_lib_rule,esp_event,$(ESPIDF_ESP_EVENT_O))) +$(eval $(call gen_espidf_lib_rule,esp_wifi,$(ESPIDF_ESP_WIFI_O))) +$(eval $(call gen_espidf_lib_rule,esp_eth,$(ESPIDF_ESP_ETH_O))) +$(eval $(call gen_espidf_lib_rule,xtensa,$(ESPIDF_XTENSA_O))) +else +$(eval $(call gen_espidf_lib_rule,ethernet,$(ESPIDF_ETHERNET_O))) +endif + # Create all destination build dirs before compiling IDF source OBJ_ESPIDF_DIRS = $(sort $(dir $(OBJ_ESPIDF))) $(BUILD_ESPIDF_LIB) $(addprefix $(BUILD_ESPIDF_LIB)/,$(LIB_ESPIDF)) $(OBJ_ESPIDF): | $(OBJ_ESPIDF_DIRS) @@ -451,6 +527,32 @@ LIB = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) # ESP IDF ldgen LDGEN_FRAGMENTS = $(shell find $(ESPCOMP) -name "*.lf") + +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) + +LDGEN_LIBRARIES=$(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a) + +$(BUILD_ESPIDF_LIB)/ldgen_libraries: $(LDGEN_LIBRARIES) $(ESPIDF)/make/ldgen.mk + printf "$(foreach library,$(LDGEN_LIBRARIES),$(library)\n)" > $(BUILD_ESPIDF_LIB)/ldgen_libraries + +$(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGMENTS) $(SDKCONFIG_COMBINED) $(BUILD_ESPIDF_LIB)/ldgen_libraries + $(ECHO) "GEN $@" + $(Q)$(PYTHON) $(ESPIDF)/tools/ldgen/ldgen.py \ + --input $< \ + --output $@ \ + --config $(SDKCONFIG_COMBINED) \ + --kconfig $(ESPIDF)/Kconfig \ + --fragments $(LDGEN_FRAGMENTS) \ + --libraries-file $(BUILD_ESPIDF_LIB)/ldgen_libraries \ + --env "IDF_TARGET=esp32" \ + --env "IDF_CMAKE=n" \ + --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ + --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ + --env "IDF_PATH=$(ESPIDF)" \ + --objdump $(OBJDUMP) + +else + LDGEN_SECTIONS_INFO = $(foreach lib,$(LIB_ESPIDF),$(BUILD_ESPIDF_LIB)/$(lib)/lib$(lib).a.sections_info) LDGEN_SECTION_INFOS = $(BUILD_ESPIDF_LIB)/ldgen.section_infos @@ -477,7 +579,10 @@ $(BUILD)/esp32.project.ld: $(ESPCOMP)/esp32/ld/esp32.project.ld.in $(LDGEN_FRAGM --env "IDF_TARGET=esp32" \ --env "IDF_CMAKE=n" \ --env "COMPONENT_KCONFIGS=$(ESPCOMP_KCONFIGS)" \ - --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" + --env "COMPONENT_KCONFIGS_PROJBUILD=$(ESPCOMP_KCONFIGS_PROJBUILD)" \ + --env "IDF_PATH=$(ESPIDF)" + +endif ################################################################################ # Main targets @@ -513,8 +618,13 @@ APP_LD_ARGS += --start-group APP_LD_ARGS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ APP_LD_ARGS += $(LIBC_LIBM) +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +APP_LD_ARGS += -L$(ESPCOMP)/xtensa/esp32 -lhal +APP_LD_ARGS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lsmartconfig -lcoexist +else APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 +endif APP_LD_ARGS += $(OBJ) APP_LD_ARGS += $(LIB) APP_LD_ARGS += --end-group @@ -553,7 +663,14 @@ $(BUILD)/%.o: %.cpp BOOTLOADER_LIB_DIR = $(BUILD)/bootloader BOOTLOADER_LIB_ALL = +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +$(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/efuse/include -I$(ESPCOMP)/esp_rom/include -Wno-error=format \ + -I$(ESPCOMP)/esp_common/include \ + -I$(ESPCOMP)/xtensa/include \ + -I$(ESPCOMP)/xtensa/esp32/include +else $(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/micro-ecc/micro-ecc -I$(ESPCOMP)/efuse/include -I$(ESPCOMP)/esp32 -Wno-error=format +endif # libbootloader_support.a BOOTLOADER_LIB_ALL += bootloader_support @@ -563,15 +680,27 @@ BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOM bootloader_support/src/bootloader_flash.o \ bootloader_support/src/bootloader_init.o \ bootloader_support/src/bootloader_random.o \ - bootloader_support/src/bootloader_sha.o \ bootloader_support/src/bootloader_utility.o \ bootloader_support/src/flash_qio_mode.o \ - bootloader_support/src/secure_boot_signatures.o \ - bootloader_support/src/secure_boot.o \ bootloader_support/src/esp_image_format.o \ bootloader_support/src/flash_encrypt.o \ bootloader_support/src/flash_partitions.o \ ) + +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ + bootloader_support/src/esp32/bootloader_sha.o \ + bootloader_support/src/bootloader_flash_config.o \ + bootloader_support/src/esp32/secure_boot.o \ + ) +else +BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ += $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ + bootloader_support/src/bootloader_sha.o \ + bootloader_support/src/secure_boot_signatures.o \ + bootloader_support/src/secure_boot.o \ + ) +endif + $(BOOTLOADER_LIB_DIR)/libbootloader_support.a: $(BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ @@ -594,6 +723,7 @@ $(BOOTLOADER_LIB_DIR)/libspi_flash.a: $(BOOTLOADER_LIB_SPI_FLASH_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) # libmicro-ecc.a BOOTLOADER_LIB_ALL += micro-ecc BOOTLOADER_LIB_MICRO_ECC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ @@ -602,6 +732,7 @@ BOOTLOADER_LIB_MICRO_ECC_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ $(BOOTLOADER_LIB_DIR)/libmicro-ecc.a: $(BOOTLOADER_LIB_MICRO_ECC_OBJ) $(ECHO) "AR $@" $(Q)$(AR) cr $@ $^ +endif # libsoc.a $(BUILD)/bootloader/$(ESPCOMP)/soc/esp32/rtc_clk.o: CFLAGS += -fno-jump-tables -fno-tree-switch-conversion @@ -651,7 +782,11 @@ BOOTLOADER_LIBS = BOOTLOADER_LIBS += -Wl,--start-group BOOTLOADER_LIBS += $(BOOTLOADER_OBJ) BOOTLOADER_LIBS += -L$(BUILD)/bootloader $(addprefix -l,$(BOOTLOADER_LIB_ALL)) +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +BOOTLOADER_LIBS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lrtc +else BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc +endif BOOTLOADER_LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc BOOTLOADER_LIBS += -Wl,--end-group @@ -666,8 +801,13 @@ BOOTLOADER_LDFLAGS += -Wl,-EL BOOTLOADER_LDFLAGS += -Wl,-Map=$(@:.elf=.map) -Wl,--cref BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.ld BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.rom.ld +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.ld +BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld +else BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.ld BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.spiram_incompatible_fns.ld +endif BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.peripherals.ld BOOTLOADER_OBJ_DIRS = $(sort $(dir $(BOOTLOADER_OBJ_ALL))) diff --git a/ports/esp32/boards/TINYPICO/sdkconfig.board b/ports/esp32/boards/TINYPICO/sdkconfig.board index ea4fc9b5cd51b..dc2c23f674e84 100644 --- a/ports/esp32/boards/TINYPICO/sdkconfig.board +++ b/ports/esp32/boards/TINYPICO/sdkconfig.board @@ -1,3 +1,4 @@ CONFIG_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_80M=y CONFIG_SPIRAM_SPEED_80M=y +CONFIG_ESP32_REV_MIN_1=y diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index 7bd731a66b6c5..d44a97e138dd9 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -8,7 +8,7 @@ CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y # Bootloader config -CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y # ESP32-specific CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y @@ -21,10 +21,15 @@ CONFIG_PM_ENABLE=y # FreeRTOS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2 -CONFIG_SUPPORT_STATIC_ALLOCATION=y -CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y # UDP CONFIG_PPP_SUPPORT=y CONFIG_PPP_PAP_SUPPORT=y CONFIG_PPP_CHAP_SUPPORT=y + +# v3.3-only (renamed in 4.0) +CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y +CONFIG_SUPPORT_STATIC_ALLOCATION=y +CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y diff --git a/ports/esp32/boards/sdkconfig.spiram b/ports/esp32/boards/sdkconfig.spiram index 53950e587c074..db1a83af8c432 100644 --- a/ports/esp32/boards/sdkconfig.spiram +++ b/ports/esp32/boards/sdkconfig.spiram @@ -1,5 +1,9 @@ # MicroPython on ESP32, ESP IDF configuration with SPIRAM support -CONFIG_SPIRAM_SUPPORT=y +CONFIG_ESP32_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_CACHE_WORKAROUND=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_USE_MEMMAP=y + +# v3.3-only (renamed in 4.0) +CONFIG_SPIRAM_SUPPORT=y diff --git a/ports/esp32/esp32_ulp.c b/ports/esp32/esp32_ulp.c index 3772639f4416a..bf11de330fac9 100644 --- a/ports/esp32/esp32_ulp.c +++ b/ports/esp32/esp32_ulp.c @@ -85,7 +85,11 @@ STATIC const mp_rom_map_elem_t esp32_ulp_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_wakeup_period), MP_ROM_PTR(&esp32_ulp_set_wakeup_period_obj) }, { MP_ROM_QSTR(MP_QSTR_load_binary), MP_ROM_PTR(&esp32_ulp_load_binary_obj) }, { MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&esp32_ulp_run_obj) }, + #if !MICROPY_ESP_IDF_4 { MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ULP_COPROC_RESERVE_MEM) }, + #else + { MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ESP32_ULP_COPROC_RESERVE_MEM) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(esp32_ulp_locals_dict, esp32_ulp_locals_dict_table); diff --git a/ports/esp32/main.c b/ports/esp32/main.c index c8dde337c5d95..4d25cf0b3a727 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -37,7 +37,11 @@ #include "esp_task.h" #include "soc/cpu.h" #include "esp_log.h" +#if MICROPY_ESP_IDF_4 +#include "esp32/spiram.h" +#else #include "esp_spiram.h" +#endif #include "py/stackctrl.h" #include "py/nlr.h" @@ -70,7 +74,7 @@ void mp_task(void *pvParameter) { #endif uart_init(); - #if CONFIG_SPIRAM_SUPPORT + #if CONFIG_ESP32_SPIRAM_SUPPORT // Try to use the entire external SPIRAM directly for the heap size_t mp_task_heap_size; void *mp_task_heap = (void*)0x3f800000; @@ -150,7 +154,11 @@ void mp_task(void *pvParameter) { } void app_main(void) { - nvs_flash_init(); + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + nvs_flash_erase(); + nvs_flash_init(); + } xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_main_task_handle, MP_TASK_COREID); } diff --git a/ports/esp32/modesp.c b/ports/esp32/modesp.c index e614f77a6aea6..9584b789dc474 100644 --- a/ports/esp32/modesp.c +++ b/ports/esp32/modesp.c @@ -29,7 +29,9 @@ #include +#if !MICROPY_ESP_IDF_4 #include "rom/gpio.h" +#endif #include "esp_log.h" #include "esp_spi_flash.h" diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index fb864947d229d..0c803d0960d18 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -32,9 +32,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#if MICROPY_ESP_IDF_4 +#include "esp32/rom/rtc.h" +#include "esp32/clk.h" +#include "esp_sleep.h" +#else #include "rom/ets_sys.h" #include "rom/rtc.h" #include "esp_clk.h" +#endif #include "esp_pm.h" #include "driver/touch_pad.h" diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 45ea5139c68f0..012dc5bce8b1e 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -43,20 +43,23 @@ #include "netutils.h" #include "esp_eth.h" #include "esp_wifi.h" -#include "esp_wifi_types.h" #include "esp_log.h" -#include "esp_event_loop.h" #include "lwip/dns.h" #include "tcpip_adapter.h" #include "mdns.h" +#if !MICROPY_ESP_IDF_4 +#include "esp_wifi_types.h" +#include "esp_event_loop.h" +#endif + #include "modnetwork.h" #define MODNETWORK_INCLUDE_CONSTANTS (1) NORETURN void _esp_exceptions(esp_err_t e) { switch (e) { - case ESP_ERR_WIFI_NOT_INIT: + case ESP_ERR_WIFI_NOT_INIT: mp_raise_msg(&mp_type_OSError, "Wifi Not Initialized"); case ESP_ERR_WIFI_NOT_STARTED: mp_raise_msg(&mp_type_OSError, "Wifi Not Started"); @@ -93,7 +96,7 @@ NORETURN void _esp_exceptions(esp_err_t e) { case ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED: mp_raise_msg(&mp_type_OSError, "TCP/IP DHCP Client Start Failed"); case ESP_ERR_TCPIP_ADAPTER_NO_MEM: - mp_raise_OSError(MP_ENOMEM); + mp_raise_OSError(MP_ENOMEM); default: nlr_raise(mp_obj_new_exception_msg_varg( &mp_type_RuntimeError, "Wifi Unknown Error 0x%04x", e @@ -650,9 +653,12 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs ESP_EXCEPTIONS(esp_wifi_get_mac(self->if_id, mac)); return mp_obj_new_bytes(mac, sizeof(mac)); + #if !MICROPY_ESP_IDF_4 case ESP_IF_ETH: esp_eth_get_mac(mac); return mp_obj_new_bytes(mac, sizeof(mac)); + #endif + default: goto unknown; } @@ -734,8 +740,10 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_initialize_obj) }, { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) }, + #if !MICROPY_ESP_IDF_4 { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) }, { MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&ppp_make_new_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) }, #if MODNETWORK_INCLUDE_CONSTANTS @@ -757,12 +765,14 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PHY_TLK110), MP_ROM_INT(PHY_TLK110) }, // ETH Clock modes from ESP-IDF + #if !MICROPY_ESP_IDF_4 { MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO0_IN), MP_ROM_INT(ETH_CLOCK_GPIO0_IN) }, // Disabled at Aug 22nd 2018, reenabled Jan 28th 2019 in ESP-IDF // Because we use older SDK, it's currently disabled //{ MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO0_OUT), MP_ROM_INT(ETH_CLOCK_GPIO0_OUT) }, { MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO16_OUT), MP_ROM_INT(ETH_CLOCK_GPIO16_OUT) }, { MP_ROM_QSTR(MP_QSTR_ETH_CLOCK_GPIO17_OUT), MP_ROM_INT(ETH_CLOCK_GPIO17_OUT) }, + #endif { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STAT_IDLE)}, { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STAT_CONNECTING)}, diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index a6f29718d8e17..e11af60e2e1cb 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -56,6 +56,18 @@ #include "lwip/igmp.h" #include "esp_log.h" +#if !MICROPY_ESP_IDF_4 +#define lwip_bind lwip_bind_r +#define lwip_listen lwip_listen_r +#define lwip_accept lwip_accept_r +#define lwip_setsockopt lwip_setsockopt_r +#define lwip_fnctl lwip_fnctl_r +#define lwip_recvfrom lwip_recvfrom_r +#define lwip_write lwip_write_r +#define lwip_sendto lwip_sendto_r +#define lwip_close lwip_close_r +#endif + #define SOCKET_POLL_US (100000) #define MDNS_QUERY_TIMEOUT_MS (5000) #define MDNS_LOCAL_SUFFIX ".local" @@ -277,17 +289,17 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); struct addrinfo *res; _socket_getaddrinfo(arg1, &res); - int r = lwip_bind_r(self->fd, res->ai_addr, res->ai_addrlen); + int r = lwip_bind(self->fd, res->ai_addr, res->ai_addrlen); lwip_freeaddrinfo(res); if (r < 0) exception_from_errno(errno); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); - + STATIC mp_obj_t socket_listen(const mp_obj_t arg0, const mp_obj_t arg1) { socket_obj_t *self = MP_OBJ_TO_PTR(arg0); int backlog = mp_obj_get_int(arg1); - int r = lwip_listen_r(self->fd, backlog); + int r = lwip_listen(self->fd, backlog); if (r < 0) exception_from_errno(errno); return mp_const_none; } @@ -302,7 +314,7 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { int new_fd = -1; for (int i=0; i<=self->retries; i++) { MP_THREAD_GIL_EXIT(); - new_fd = lwip_accept_r(self->fd, &addr, &addr_len); + new_fd = lwip_accept(self->fd, &addr, &addr_len); MP_THREAD_GIL_ENTER(); if (new_fd >= 0) break; if (errno != EAGAIN) exception_from_errno(errno); @@ -342,7 +354,7 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) { struct addrinfo *res; _socket_getaddrinfo(arg1, &res); MP_THREAD_GIL_EXIT(); - int r = lwip_connect_r(self->fd, res->ai_addr, res->ai_addrlen); + int r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen); MP_THREAD_GIL_ENTER(); lwip_freeaddrinfo(res); if (r != 0) { @@ -363,7 +375,7 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { // level: SOL_SOCKET case SO_REUSEADDR: { int val = mp_obj_get_int(args[3]); - int ret = lwip_setsockopt_r(self->fd, SOL_SOCKET, opt, &val, sizeof(int)); + int ret = lwip_setsockopt(self->fd, SOL_SOCKET, opt, &val, sizeof(int)); if (ret != 0) { exception_from_errno(errno); } @@ -424,9 +436,9 @@ void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) { .tv_sec = 0, .tv_usec = timeout_ms ? SOCKET_POLL_US : 0 }; - lwip_setsockopt_r(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout)); - lwip_setsockopt_r(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); - lwip_fcntl_r(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK); + lwip_setsockopt(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout)); + lwip_setsockopt(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout)); + lwip_fcntl(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK); } STATIC mp_obj_t socket_settimeout(const mp_obj_t arg0, const mp_obj_t arg1) { @@ -459,7 +471,7 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, socket_obj_t *sock = MP_OBJ_TO_PTR(self_in); // If the peer closed the connection then the lwIP socket API will only return "0" once - // from lwip_recvfrom_r and then block on subsequent calls. To emulate POSIX behaviour, + // from lwip_recvfrom and then block on subsequent calls. To emulate POSIX behaviour, // which continues to return "0" for each call on a closed socket, we set a flag when // the peer closed the socket. if (sock->peer_closed) { @@ -482,7 +494,7 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, if (release_gil) { MP_THREAD_GIL_EXIT(); } - int r = lwip_recvfrom_r(sock->fd, buf, size, 0, from, from_len); + int r = lwip_recvfrom(sock->fd, buf, size, 0, from, from_len); if (release_gil) { MP_THREAD_GIL_ENTER(); } @@ -543,13 +555,13 @@ int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) { int sentlen = 0; for (int i=0; i<=sock->retries && sentlen < datalen; i++) { MP_THREAD_GIL_EXIT(); - int r = lwip_write_r(sock->fd, data+sentlen, datalen-sentlen); + int r = lwip_write(sock->fd, data+sentlen, datalen-sentlen); MP_THREAD_GIL_ENTER(); if (r < 0 && errno != EWOULDBLOCK) exception_from_errno(errno); if (r > 0) sentlen += r; check_for_exceptions(); } - if (sentlen == 0) mp_raise_OSError(MP_ETIMEDOUT); + if (sentlen == 0) mp_raise_OSError(MP_ETIMEDOUT); return sentlen; } @@ -590,7 +602,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ // send the data for (int i=0; i<=self->retries; i++) { MP_THREAD_GIL_EXIT(); - int ret = lwip_sendto_r(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to)); + int ret = lwip_sendto(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to)); MP_THREAD_GIL_ENTER(); if (ret > 0) return mp_obj_new_int_from_uint(ret); if (ret == -1 && errno != EWOULDBLOCK) { @@ -598,7 +610,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ } check_for_exceptions(); } - mp_raise_OSError(MP_ETIMEDOUT); + mp_raise_OSError(MP_ETIMEDOUT); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); @@ -622,7 +634,7 @@ STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_ socket_obj_t *sock = self_in; for (int i=0; i<=sock->retries; i++) { MP_THREAD_GIL_EXIT(); - int r = lwip_write_r(sock->fd, buf, size); + int r = lwip_write(sock->fd, buf, size); MP_THREAD_GIL_ENTER(); if (r > 0) return r; if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; } @@ -663,7 +675,7 @@ STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintpt socket->events_callback = MP_OBJ_NULL; } #endif - int ret = lwip_close_r(socket->fd); + int ret = lwip_close(socket->fd); if (ret != 0) { *errcode = errno; return MP_STREAM_ERROR; @@ -731,7 +743,7 @@ STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)), mp_const_none }; - + if (resi->ai_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *)resi->ai_addr; // This looks odd, but it's really just a u32_t diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index cba319245c94c..1c0d8700facda 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -6,7 +6,10 @@ #include #include + +#if !MICROPY_ESP_IDF_4 #include "rom/ets_sys.h" +#endif // object representation and NLR handling #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index 0d1ea74d6b342..305e87593eeb6 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -31,7 +31,12 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" + +#if MICROPY_ESP_IDF_4 +#include "esp32/rom/uart.h" +#else #include "rom/uart.h" +#endif #include "py/obj.h" #include "py/stream.h" diff --git a/ports/esp32/mpthreadport.c b/ports/esp32/mpthreadport.c index 9557d4071454a..1c0d889e98808 100644 --- a/ports/esp32/mpthreadport.c +++ b/ports/esp32/mpthreadport.c @@ -33,6 +33,9 @@ #include "mpthreadport.h" #include "esp_task.h" +#if !MICROPY_ESP_IDF_4 +#include "freertos/semphr.h" +#endif #if MICROPY_PY_THREAD diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index 100894b2eeb14..291040797381e 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -26,6 +26,7 @@ * THE SOFTWARE. */ +#if !MICROPY_ESP_IDF_4 #include "py/runtime.h" #include "py/mphal.h" @@ -216,3 +217,5 @@ const mp_obj_type_t lan_if_type = { .name = MP_QSTR_LAN, .locals_dict = (mp_obj_dict_t*)&lan_if_locals_dict, }; + +#endif // !MICROPY_ESP_IDF_4 diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index 1a14c09bf8ddb..d868450fd0279 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -26,6 +26,7 @@ * THE SOFTWARE. */ +#if !MICROPY_ESP_IDF_4 #include "py/runtime.h" #include "py/mphal.h" #include "py/objtype.h" @@ -282,3 +283,5 @@ const mp_obj_type_t ppp_if_type = { .name = MP_QSTR_PPP, .locals_dict = (mp_obj_dict_t*)&ppp_if_locals_dict, }; + +#endif // !MICROPY_ESP_IDF_4 From b1505541da5d079fdc47f58d3c7b232b46ae77fc Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 13 Sep 2019 23:48:28 +1000 Subject: [PATCH 0442/1299] travis: Add ESP32 build with IDF v4. --- .travis.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 72dbe138f7689..788bf7d574afe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -140,17 +140,26 @@ jobs: env: NAME="esp32 port build" install: - sudo apt-get install python3-pip - - sudo pip3 install pyparsing + - sudo pip3 install 'pyparsing<2.4' - wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz - zcat xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz | tar x - export PATH=$(pwd)/xtensa-esp32-elf/bin:$PATH - git clone https://github.com/espressif/esp-idf.git - - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH :=" ports/esp32/Makefile | cut -d " " -f 3) - - git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 + - export IDF_PATH=$(pwd)/esp-idf script: - git submodule update --init lib/berkeley-db-1.xx - make ${MAKEOPTS} -C mpy-cross - - make ${MAKEOPTS} -C ports/esp32 ESPIDF=$(pwd)/esp-idf + # IDF v3 build + - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V3 :=" ports/esp32/Makefile | cut -d " " -f 3) + - git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 + - make ${MAKEOPTS} -C ports/esp32 + # clean + - git -C esp-idf clean -f -f -d components/json/cJSON components/esp32/lib components/expat/expat components/micro-ecc/micro-ecc components/nghttp/nghttp2 + - make ${MAKEOPTS} -C ports/esp32 clean + # IDF v4 build + - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V4 :=" ports/esp32/Makefile | cut -d " " -f 3) + - git -C esp-idf submodule update --init components/esp_wifi/lib_esp32 components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls + - make ${MAKEOPTS} -C ports/esp32 # esp8266 port - stage: test From 970f798ea9730298f9a690cf5472839158acea4b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 17 Sep 2019 11:50:09 +1000 Subject: [PATCH 0443/1299] esp32: Add check to Makefile for pyparsing version. --- ports/esp32/Makefile | 9 +++++++++ ports/esp32/README.md | 15 +++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 25001643eedc3..bb25477444775 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -82,6 +82,15 @@ ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) $(info Building with ESP IDF v3) else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) $(info Building with ESP IDF v4) + +PYPARSING_VERSION = $(shell python3 -c 'import pyparsing; print(pyparsing.__version__)') +ifneq ($(PYPARSING_VERSION),2.3.1) +$(info ** ERROR **) +$(info EDP IDF requires pyparsing version less than 2.4) +$(info You will need to set up a Python virtual environment with pyparsing 2.3.1) +$(info Please see README.md for more information) +$(error Incorrect pyparsing version) +endif else $(info ** WARNING **) $(info The git hash of ESP IDF does not match the supported version) diff --git a/ports/esp32/README.md b/ports/esp32/README.md index 31347b6a2a6a1..2c7351ee53b55 100644 --- a/ports/esp32/README.md +++ b/ports/esp32/README.md @@ -26,14 +26,17 @@ There are two main components that are needed to build the firmware: different to the compiler used by the ESP8266) - the Espressif IDF (IoT development framework, aka SDK) -The ESP-IDF changes quickly and MicroPython only supports a certain version. The -git hash of this version can be found by running `make` without a configured -`ESPIDF`. Then you can fetch only the given esp-idf using the following command: +The ESP-IDF changes quickly and MicroPython only supports certain versions. The +git hash of these versions (one for 3.x, one for 4.x) can be found by running +`make` without a configured `ESPIDF`. Then you can fetch only the given esp-idf +using the following command: $ git clone https://github.com/espressif/esp-idf.git $ git checkout $ git submodule update --init --recursive +Note: The ESP IDF v4.x support is currently experimental. + The binary toolchain (binutils, gcc, etc.) can be installed using the following guides: @@ -53,9 +56,13 @@ You will also need either Python 2 or Python 3, along with the `pyserial` and (when building you can use, eg, `make PYTHON=python2` to specify the version used). To install the required packages do: ```bash -$ pip install pyserial pyparsing +$ pip install pyserial 'pyparsing<2.4' ``` +It is recommended to use a Python virtual environment if your system package +manager already provides these libraries, especially as the IDF v4.x is +currently incompatible with pyparsing 2.4 and higher. + Once everything is set up you should have a functioning toolchain with prefix xtensa-esp32-elf- (or otherwise if you configured it differently) as well as a copy of the ESP-IDF repository. You will need to update your `PATH` From f469634c0c72abb1af790b4ed43aae756d333412 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 17 Sep 2019 11:50:31 +1000 Subject: [PATCH 0444/1299] esp32: Add check to Makefile that the toolchain is in PATH. --- ports/esp32/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index bb25477444775..85eebb3f54768 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -103,6 +103,13 @@ endif # pretty format of ESP IDF version, used internally by the IDF IDF_VER := $(shell git -C $(ESPIDF) describe) +ifeq ($(shell which $(CC) 2> /dev/null),) +$(info ** ERROR **) +$(info Cannot find C compiler $(CC)) +$(info Add the xtensa toolchain to your PATH. See README.md) +$(error C compiler missing) +endif + # include sdkconfig to get needed configuration values include $(SDKCONFIG) From 73c94bbbd45c01c3236282e7b334e4539ca043d4 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 13 Sep 2019 19:57:23 +0200 Subject: [PATCH 0445/1299] stm32/modusocket: Fix NULL deref when accept() an unbound socket. --- ports/stm32/modusocket.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/stm32/modusocket.c b/ports/stm32/modusocket.c index 7503ecbd68d20..5a163311379e4 100644 --- a/ports/stm32/modusocket.c +++ b/ports/stm32/modusocket.c @@ -125,6 +125,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->nic == MP_OBJ_NULL) { + // not bound + mp_raise_OSError(MP_EINVAL); + } + // create new socket object // starts with empty NIC so that finaliser doesn't run close() method if accept() fails mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); From 62d78e231ceb41eecdc3180cae6f07d790cd33d8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 18 Sep 2019 10:44:16 +1000 Subject: [PATCH 0446/1299] esp32/main: Use both 3.3 and 4.0 config vars to enable SPIRAM. --- ports/esp32/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ports/esp32/main.c b/ports/esp32/main.c index 4d25cf0b3a727..7106e0bf5e4e1 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -74,7 +74,8 @@ void mp_task(void *pvParameter) { #endif uart_init(); - #if CONFIG_ESP32_SPIRAM_SUPPORT + // TODO: CONFIG_SPIRAM_SUPPORT is for 3.3 compatibility, remove after move to 4.0. + #if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_SPIRAM_SUPPORT // Try to use the entire external SPIRAM directly for the heap size_t mp_task_heap_size; void *mp_task_heap = (void*)0x3f800000; From b2b21839d374e480b900e102cfd0010233b43543 Mon Sep 17 00:00:00 2001 From: stijn Date: Wed, 29 May 2019 17:14:45 +0200 Subject: [PATCH 0447/1299] windows/msvc: Remove unneeded definitions for qstr generation. These were probably added to detect more qstrs but as long as the micropython executable itself doesn't use the same build options the qstrs would be unused anyway. Furthermore these definitions are for internal use and get enabled when corresponding MICROPY_EMIT_XXX are defined, in which case the compiler would warn about symbol redefinitions since they'd be defined both here and in the source. --- ports/windows/msvc/genhdr.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/windows/msvc/genhdr.targets b/ports/windows/msvc/genhdr.targets index db8cfea7d75eb..5382b79d92d2f 100644 --- a/ports/windows/msvc/genhdr.targets +++ b/ports/windows/msvc/genhdr.targets @@ -54,7 +54,7 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) { - + $([System.String]::new('%(FullPath)').Replace('$(PyBaseDir)', '$(DestDir)qstr\')) From 94873a48263d5923ba0640900b801b13fcd309d7 Mon Sep 17 00:00:00 2001 From: stijn Date: Fri, 11 Aug 2017 15:33:39 +0200 Subject: [PATCH 0448/1299] windows/msvc: Move build options from .vcxproj to .props files. We want the .vcxproj to be just a container with the minimum content for making it work as a project file for Visual Studio and MSBuild, whereas the actual build options and actions get placed in separate reusable files. This was roughly the case already except some compiler options were overlooked; fix this here: we'll need those common options when adding a project file for building mpy-cross. --- ports/windows/micropython.vcxproj | 10 ---------- ports/windows/msvc/common.props | 1 + ports/windows/msvc/debug.props | 2 ++ ports/windows/msvc/release.props | 5 ++++- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/ports/windows/micropython.vcxproj b/ports/windows/micropython.vcxproj index ee0b98abba871..e468cfdae8514 100644 --- a/ports/windows/micropython.vcxproj +++ b/ports/windows/micropython.vcxproj @@ -25,29 +25,19 @@ Application - true $(DefaultPlatformToolset) - MultiByte Application - false $(DefaultPlatformToolset) - true - MultiByte Application - true $(DefaultPlatformToolset) - MultiByte Application - false $(DefaultPlatformToolset) - true - MultiByte diff --git a/ports/windows/msvc/common.props b/ports/windows/msvc/common.props index 5fe1b45fefb6a..6735f96d708e8 100644 --- a/ports/windows/msvc/common.props +++ b/ports/windows/msvc/common.props @@ -8,6 +8,7 @@ $(PyOutDir) $(PyIntDir) $(PyBuildDir)copycookie$(Configuration)$(Platform) + MultiByte diff --git a/ports/windows/msvc/debug.props b/ports/windows/msvc/debug.props index fa1ca4fcbc998..5ae9d64fcd877 100644 --- a/ports/windows/msvc/debug.props +++ b/ports/windows/msvc/debug.props @@ -3,6 +3,8 @@ + true + false diff --git a/ports/windows/msvc/release.props b/ports/windows/msvc/release.props index ea0bf433d3a18..a3fbe2494fde2 100644 --- a/ports/windows/msvc/release.props +++ b/ports/windows/msvc/release.props @@ -2,7 +2,10 @@ - + + false + true + true From 146c32a14196356fbf3c3b5f2a7c6e41e3b59389 Mon Sep 17 00:00:00 2001 From: stijn Date: Mon, 14 Aug 2017 12:12:30 +0200 Subject: [PATCH 0449/1299] windows/msvc: Enable overriding directories used in the build. Append to PyIncDirs, used to define include directories specific to MicroPython, instead of just overwriting it so project files importing this file can define additional directories. And allow defining the target directory for the executable instead of hardcoding it to the windows directory. Main reason for this change is that it will allow building mpy-cross with msvc. --- ports/windows/msvc/common.props | 2 +- ports/windows/msvc/paths.props | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/windows/msvc/common.props b/ports/windows/msvc/common.props index 6735f96d708e8..2545a36469023 100644 --- a/ports/windows/msvc/common.props +++ b/ports/windows/msvc/common.props @@ -28,7 +28,7 @@ - $(PyWinDir)%(FileName)%(Extension) + $(PyTargetDir)%(FileName)%(Extension) diff --git a/ports/windows/msvc/paths.props b/ports/windows/msvc/paths.props index db3af4c0faaa3..cfd43b708cd9f 100644 --- a/ports/windows/msvc/paths.props +++ b/ports/windows/msvc/paths.props @@ -26,9 +26,10 @@ $([System.IO.Path]::GetFullPath(`$(MSBuildThisFileDirectory)..\..\..`))\ $(PyBaseDir)ports\windows\ $(PyWinDir)build\ + $(PyWinDir) - $(PyBaseDir);$(PyWinDir);$(PyBuildDir);$(PyWinDir)msvc + $(PyIncDirs);$(PyBaseDir);$(PyWinDir);$(PyBuildDir);$(PyWinDir)msvc already in queue\n"); + return; + } + if (ev2->next == NULL) { + break; + } + DEBUG_EVENT_printf(" --> %p\n", ev2->next); + ev2 = ev2->next; + } + ev2->next = ev; + ev->prev = ev2; + } +} + +void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg) { + DEBUG_EVENT_printf("ble_npl_event_init(%p, %p, %p)\n", ev, fn, arg); + ev->fn = fn; + ev->arg = arg; + ev->next = NULL; +} + +void *ble_npl_event_get_arg(struct ble_npl_event *ev) { + DEBUG_EVENT_printf("ble_npl_event_get_arg(%p) -> %p\n", ev, ev->arg); + return ev->arg; +} + +void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) { + DEBUG_EVENT_printf("ble_npl_event_set_arg(%p, %p)\n", ev, arg); + ev->arg = arg; +} + +/******************************************************************************/ +// MUTEX + +ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu) { + DEBUG_MUTEX_printf("ble_npl_mutex_init(%p)\n", mu); + mu->locked = 0; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) { + DEBUG_MUTEX_printf("ble_npl_mutex_pend(%p, %u) locked=%u\n", mu, (uint)timeout, (uint)mu->locked); + mu->locked = 1; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu) { + DEBUG_MUTEX_printf("ble_npl_mutex_release(%p) locked=%u\n", mu, (uint)mu->locked); + mu->locked = 0; + return BLE_NPL_OK; +} + +/******************************************************************************/ +// SEM + +ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) { + DEBUG_SEM_printf("ble_npl_sem_init(%p, %u)\n", sem, (uint)tokens); + sem->count = tokens; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) { + DEBUG_SEM_printf("ble_npl_sem_pend(%p, %u) count=%u\n", sem, (uint)timeout, (uint)sem->count); + if (sem->count == 0) { + uint32_t t0 = mp_hal_ticks_ms(); + while (sem->count == 0 && mp_hal_ticks_ms() - t0 < timeout) { + extern void nimble_uart_process(void); + nimble_uart_process(); + if (sem->count != 0) { + break; + } + __WFI(); + } + if (sem->count == 0) { + printf("timeout\n"); + return BLE_NPL_TIMEOUT; + } + DEBUG_SEM_printf("got response in %u ms\n", (int)(mp_hal_ticks_ms() - t0)); + } + sem->count -= 1; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem) { + DEBUG_SEM_printf("ble_npl_sem_release(%p)\n", sem); + sem->count += 1; + return BLE_NPL_OK; +} + +uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem) { + DEBUG_SEM_printf("ble_npl_sem_get_count(%p)\n", sem); + return sem->count; +} + +/******************************************************************************/ +// CALLOUT + +static struct ble_npl_callout *global_callout = NULL; + +void os_callout_process(void) { + uint32_t tnow = mp_hal_ticks_ms(); + for (struct ble_npl_callout *c = global_callout; c != NULL; c = c->nextc) { + if (!c->active) { + continue; + } + if ((int32_t)(tnow - c->ticks) >= 0) { + DEBUG_CALLOUT_printf("callout_run(%p) tnow=%u ticks=%u evq=%p\n", c, (uint)tnow, (uint)c->ticks, c->evq); + c->active = false; + if (c->evq) { + ble_npl_eventq_put(c->evq, &c->ev); + } else { + c->ev.fn(&c->ev); + } + DEBUG_CALLOUT_printf("callout_run(%p) done\n", c); + } + } +} + +void ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq, ble_npl_event_fn *ev_cb, void *ev_arg) { + DEBUG_CALLOUT_printf("ble_npl_callout_init(%p, %p, %p, %p)\n", c, evq, ev_cb, ev_arg); + c->active = false; + c->ticks = 0; + c->evq = evq; + ble_npl_event_init(&c->ev, ev_cb, ev_arg); + + struct ble_npl_callout **c2; + for (c2 = &global_callout; *c2 != NULL; c2 = &(*c2)->nextc) { + if (c == *c2) { + // callout already in linked list so don't link it in again + return; + } + } + *c2 = c; + c->nextc = NULL; +} + +ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *c, ble_npl_time_t ticks) { + DEBUG_CALLOUT_printf("ble_npl_callout_reset(%p, %u) tnow=%u\n", c, (uint)ticks, (uint)mp_hal_ticks_ms()); + c->active = true; + c->ticks = ble_npl_time_get() + ticks; + return BLE_NPL_OK; +} + +void ble_npl_callout_stop(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_stop(%p)\n", c); + c->active = false; +} + +bool ble_npl_callout_is_active(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_is_active(%p)\n", c); + return c->active; +} + +ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_get_ticks(%p)\n", c); + return c->ticks; +} + +ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *c, ble_npl_time_t now) { + DEBUG_CALLOUT_printf("ble_npl_callout_remaining_ticks(%p, %u)\n", c, (uint)now); + if (c->ticks > now) { + return c->ticks - now; + } else { + return 0; + } +} + +void *ble_npl_callout_get_arg(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_get_arg(%p)\n", c); + return ble_npl_event_get_arg(&c->ev); +} + +void ble_npl_callout_set_arg(struct ble_npl_callout *c, void *arg) { + DEBUG_CALLOUT_printf("ble_npl_callout_set_arg(%p, %p)\n", c, arg); + ble_npl_event_set_arg(&c->ev, arg); +} + +/******************************************************************************/ +// TIME + +uint32_t ble_npl_time_get(void) { + DEBUG_TIME_printf("ble_npl_time_get -> %u\n", (uint)mp_hal_ticks_ms()); + return mp_hal_ticks_ms(); +} + +ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) { + DEBUG_TIME_printf("ble_npl_time_ms_to_ticks(%u)\n", (uint)ms); + *out_ticks = ms; + return BLE_NPL_OK; +} + +ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms) { + DEBUG_TIME_printf("ble_npl_time_ms_to_ticks32(%u)\n", (uint)ms); + return ms; +} + +uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) { + DEBUG_TIME_printf("ble_npl_time_ticks_to_ms32(%u)\n", (uint)ticks); + return ticks; +} + +void ble_npl_time_delay(ble_npl_time_t ticks) { + mp_hal_delay_ms(ticks + 1); +} + +/******************************************************************************/ +// CRITICAL + +uint32_t ble_npl_hw_enter_critical(void) { + DEBUG_CRIT_printf("ble_npl_hw_enter_critical()\n"); + return raise_irq_pri(15); +} + +void ble_npl_hw_exit_critical(uint32_t ctx) { + DEBUG_CRIT_printf("ble_npl_hw_exit_critical(%u)\n", (uint)ctx); + restore_irq_pri(ctx); +} diff --git a/extmod/nimble/syscfg/syscfg.h b/extmod/nimble/syscfg/syscfg.h new file mode 100644 index 0000000000000..0d3acf9a7689b --- /dev/null +++ b/extmod/nimble/syscfg/syscfg.h @@ -0,0 +1,160 @@ +#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H +#define MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H + +#include "py/mphal.h" +#include "uart.h" + +void *nimble_malloc(size_t size); +void nimble_free(void *ptr); +void *nimble_realloc(void *ptr, size_t size); + +#define malloc(size) nimble_malloc(size) +#define free(ptr) nimble_free(ptr) +#define realloc(ptr, size) nimble_realloc(ptr, size) + +int nimble_sprintf(char *str, const char *fmt, ...); +#define sprintf(str, fmt, ...) nimble_sprintf(str, fmt, __VA_ARGS__) + +#define MYNEWT_VAL(x) MYNEWT_VAL_ ## x + +#define MYNEWT_VAL_LOG_LEVEL (255) + +/*** compiler/arm-none-eabi-m4 */ +#define MYNEWT_VAL_HARDFLOAT (1) + +/*** kernel/os */ +#define MYNEWT_VAL_FLOAT_USER (0) +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12) +#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292) +#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0) +#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0) +#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) +#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) +#define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0) +#define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4) +#define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024) +#define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127) +#define MYNEWT_VAL_OS_MEMPOOL_CHECK (0) +#define MYNEWT_VAL_OS_MEMPOOL_POISON (0) + +/*** nimble */ +#define MYNEWT_VAL_BLE_EXT_ADV (0) +#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) +#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1) +#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0) +#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) +#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1) +#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1) +#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1) +#define MYNEWT_VAL_BLE_WHITELIST (1) + +/*** nimble/host */ +#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256) +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1) +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64) +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000) +#define MYNEWT_VAL_BLE_ATT_SVR_READ (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) +#define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_INDICATE (1) +#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4) +#define MYNEWT_VAL_BLE_GATT_NOTIFY (1) +#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8) +#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000) +#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4) +#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_HOST (1) +#define MYNEWT_VAL_BLE_HS_DEBUG (0) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0) +#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0) +#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1) +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0) +#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1) +#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS) +#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000) +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) +#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128) +#define MYNEWT_VAL_BLE_MONITOR_RTT (0) +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1) +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("monitor") +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256) +#define MYNEWT_VAL_BLE_MONITOR_UART (0) +#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000) +#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) +#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0") +#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) +#define MYNEWT_VAL_BLE_SM_BONDING (0) +#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) +#define MYNEWT_VAL_BLE_SM_KEYPRESS (0) +#define MYNEWT_VAL_BLE_SM_LEGACY (1) +#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1) +#define MYNEWT_VAL_BLE_SM_MITM (0) +#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0) +#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_SM_SC (1) +#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3) +#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8) + +/*** nimble/host/services/gap */ +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0) +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1) +#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1) +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("pybd") +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31) +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0) + +/* Overridden by targets/porting-nimble (defined by nimble/transport) */ +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN (0) +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM (0) +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET (0) +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1) + +/*** nimble/transport/uart */ +#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (12) +#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255) +#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12) +#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70) +#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (8) +#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (8) + +/* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */ +#define MYNEWT_VAL_BLE_HCI_UART_BAUD (MICROPY_HW_BLE_UART_BAUDRATE) +#define MYNEWT_VAL_BLE_HCI_UART_DATA_BITS (8) +#define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (1) +#define MYNEWT_VAL_BLE_HCI_UART_PARITY (HAL_UART_PARITY_NONE) +#define MYNEWT_VAL_BLE_HCI_UART_PORT (MICROPY_HW_BLE_UART_ID) +#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1) + +#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H From d72dbb822c96c003a202565006a97a2bfdff9210 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sun, 29 Sep 2019 23:04:58 +1000 Subject: [PATCH 0491/1299] stm32: Provide port-specific implementation for Nimble on STM32. --- .travis.yml | 2 +- ports/stm32/Makefile | 9 ++++ ports/stm32/main.c | 11 ++++ ports/stm32/modnetwork.c | 5 ++ ports/stm32/mpconfigport.h | 9 +++- ports/stm32/nimble_hci_uart.c | 96 +++++++++++++++++++++++++++++++++++ ports/stm32/pendsv.h | 5 +- ports/stm32/systick.h | 3 ++ 8 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 ports/stm32/nimble_hci_uart.c diff --git a/.travis.yml b/.travis.yml index 708329aa12474..a72f3bc1a3192 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ jobs: - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: - - git submodule update --init lib/lwip lib/mbedtls lib/stm32lib + - git submodule update --init lib/lwip lib/mbedtls lib/stm32lib lib/mynewt-nimble - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 8dde85129745f..0e3b4f8e3339b 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -428,6 +428,15 @@ CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' SRC_MOD += mbedtls/mbedtls_port.c endif +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) +include $(TOP)/extmod/nimble/nimble.mk +SRC_C += nimble_hci_uart.c +EXTMOD_SRC_C += extmod/modbluetooth_nimble.c +ifeq ($(MICROPY_PY_NETWORK_CYW43),1) +DRIVERS_SRC_C += drivers/cyw43/cywbt.c +endif +endif + OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 48ad3b8be4625..2da3626f1294b 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -43,6 +43,10 @@ #include "drivers/cyw43/cyw43.h" #endif +#if MICROPY_BLUETOOTH_NIMBLE +#include "extmod/modbluetooth.h" +#endif + #include "mpu.h" #include "systick.h" #include "pendsv.h" @@ -500,6 +504,10 @@ void stm32_main(uint32_t reset_mode) { #endif systick_enable_dispatch(SYSTICK_DISPATCH_LWIP, mod_network_lwip_poll_wrapper); #endif + #if MICROPY_BLUETOOTH_NIMBLE + extern void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms); + systick_enable_dispatch(SYSTICK_DISPATCH_NIMBLE, mod_bluetooth_nimble_poll_wrapper); + #endif #if MICROPY_PY_NETWORK_CYW43 { @@ -729,6 +737,9 @@ void stm32_main(uint32_t reset_mode) { #endif printf("MPY: soft reboot\n"); + #if MICROPY_BLUETOOTH_NIMBLE + mp_bluetooth_deinit(); + #endif #if MICROPY_PY_NETWORK mod_network_deinit(); #endif diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index 13ecf444f0c5f..19a60103f8f19 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -63,6 +63,11 @@ STATIC void pyb_lwip_poll(void) { // Run the lwIP internal updates sys_check_timeouts(); + + #if MICROPY_BLUETOOTH_NIMBLE + extern void nimble_poll(void); + nimble_poll(); + #endif } void mod_network_lwip_poll_wrapper(uint32_t ticks_ms) { diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 20554d9e626e4..b9c6cdedd7326 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -289,6 +289,12 @@ extern const struct _mp_obj_module_t mp_module_onewire; #define MICROPY_PORT_ROOT_POINTER_MBEDTLS #endif +#if MICROPY_BLUETOOTH_NIMBLE +#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE void **bluetooth_nimble_memory; +#else +#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE +#endif + #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ \ @@ -318,7 +324,8 @@ extern const struct _mp_obj_module_t mp_module_onewire; /* list of registered NICs */ \ mp_obj_list_t mod_network_nic_list; \ \ - MICROPY_PORT_ROOT_POINTER_MBEDTLS + MICROPY_PORT_ROOT_POINTER_MBEDTLS \ + MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \ // type definitions for the specific machine diff --git a/ports/stm32/nimble_hci_uart.c b/ports/stm32/nimble_hci_uart.c new file mode 100644 index 0000000000000..104a64b732838 --- /dev/null +++ b/ports/stm32/nimble_hci_uart.c @@ -0,0 +1,96 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" +#include "uart.h" +#include "pendsv.h" +#include "drivers/cyw43/cywbt.h" + +#if MICROPY_BLUETOOTH_NIMBLE + +/******************************************************************************/ +// UART +pyb_uart_obj_t bt_hci_uart_obj; +static uint8_t hci_uart_rxbuf[512]; + +extern void nimble_poll(void); + +mp_obj_t mp_uart_interrupt(mp_obj_t self_in) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mp_uart_interrupt_obj, mp_uart_interrupt); + +int nimble_hci_uart_set_baudrate(uint32_t baudrate) { + uart_init(&bt_hci_uart_obj, baudrate, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, UART_HWCONTROL_RTS | UART_HWCONTROL_CTS); + uart_set_rxbuf(&bt_hci_uart_obj, sizeof(hci_uart_rxbuf), hci_uart_rxbuf); + return 0; +} + +int nimble_hci_uart_configure(uint32_t port) { + // bits (8), stop (1), parity (none) and flow (rts/cts) are assumed to match MYNEWT_VAL_BLE_HCI_UART_ constants in syscfg.h. + bt_hci_uart_obj.base.type = &pyb_uart_type; + bt_hci_uart_obj.uart_id = port; + bt_hci_uart_obj.is_static = true; + bt_hci_uart_obj.timeout = 2; + bt_hci_uart_obj.timeout_char = 2; + MP_STATE_PORT(pyb_uart_obj_all)[bt_hci_uart_obj.uart_id - 1] = &bt_hci_uart_obj; + return 0; +} + +int nimble_hci_uart_activate(void) { + // Interrupt on RX chunk received (idle) + // Trigger nimble poll when this happens + mp_obj_t uart_irq_fn = mp_load_attr(&bt_hci_uart_obj, MP_QSTR_irq); + mp_obj_t uargs[] = { + MP_OBJ_FROM_PTR(&mp_uart_interrupt_obj), + MP_OBJ_NEW_SMALL_INT(UART_FLAG_IDLE), + mp_const_true, + }; + mp_call_function_n_kw(uart_irq_fn, 3, 0, uargs); + + #if MICROPY_PY_NETWORK_CYW43 + cywbt_init(); + cywbt_activate(); + #endif + + return 0; +} + +mp_uint_t nimble_hci_uart_rx_any() { + return uart_rx_any(&bt_hci_uart_obj); +} + +int nimble_hci_uart_rx_char() { + return uart_rx_char(&bt_hci_uart_obj); +} + +void nimble_hci_uart_tx_strn(const char *str, uint len) { + uart_tx_strn(&bt_hci_uart_obj, str, len); +} + +#endif // MICROPY_BLUETOOTH_NIMBLE diff --git a/ports/stm32/pendsv.h b/ports/stm32/pendsv.h index 6cbfe8b2ecf1a..9851a5ece7b9c 100644 --- a/ports/stm32/pendsv.h +++ b/ports/stm32/pendsv.h @@ -33,10 +33,13 @@ enum { PENDSV_DISPATCH_CYW43, #endif #endif + #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE + PENDSV_DISPATCH_NIMBLE, + #endif PENDSV_DISPATCH_MAX }; -#if MICROPY_PY_NETWORK && MICROPY_PY_LWIP +#if (MICROPY_PY_NETWORK && MICROPY_PY_LWIP) || (MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE) #define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX #endif diff --git a/ports/stm32/systick.h b/ports/stm32/systick.h index 6a05a4990ac6a..a70f03e176a30 100644 --- a/ports/stm32/systick.h +++ b/ports/stm32/systick.h @@ -37,6 +37,9 @@ enum { #if MICROPY_PY_NETWORK && MICROPY_PY_LWIP SYSTICK_DISPATCH_LWIP, #endif + #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE + SYSTICK_DISPATCH_NIMBLE, + #endif SYSTICK_DISPATCH_MAX }; From 42e9bdf19b417e46e957b6f0c5592bb316ceeca2 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 27 Aug 2019 16:35:02 +1000 Subject: [PATCH 0492/1299] py/ringbuf: Add helpers for put16/get16. --- py/py.mk | 1 + py/ringbuf.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ py/ringbuf.h | 17 +++++++++++++- 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 py/ringbuf.c diff --git a/py/py.mk b/py/py.mk index a3d9e790fc783..d30ee81bc1fbe 100644 --- a/py/py.mk +++ b/py/py.mk @@ -85,6 +85,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ runtime_utils.o \ scheduler.o \ nativeglue.o \ + ringbuf.o \ stackctrl.o \ argcheck.o \ warning.o \ diff --git a/py/ringbuf.c b/py/ringbuf.c new file mode 100644 index 0000000000000..8795e1eda99be --- /dev/null +++ b/py/ringbuf.c @@ -0,0 +1,66 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jim Mussared + * + * 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 "ringbuf.h" + +int ringbuf_get16(ringbuf_t *r) { + if (r->iget == r->iput) { + return -1; + } + uint32_t iget_a = r->iget + 1; + if (iget_a == r->size) { + iget_a = 0; + } + if (iget_a == r->iput) { + return -1; + } + uint16_t v = (r->buf[r->iget] << 8) | (r->buf[iget_a]); + r->iget = iget_a + 1; + if (r->iget == r->size) { + r->iget = 0; + } + return v; +} + +int ringbuf_put16(ringbuf_t *r, uint16_t v) { + uint32_t iput_a = r->iput + 1; + if (iput_a == r->size) { + iput_a = 0; + } + if (iput_a == r->iget) { + return -1; + } + uint32_t iput_b = iput_a + 1; + if (iput_b == r->size) { + iput_b = 0; + } + if (iput_b == r->iget) { + return -1; + } + r->buf[r->iput] = (v >> 8) & 0xff; + r->buf[iput_a] = v & 0xff; + r->iput = iput_b; + return 0; +} diff --git a/py/ringbuf.h b/py/ringbuf.h index b4169270608a5..6b0d209bd1434 100644 --- a/py/ringbuf.h +++ b/py/ringbuf.h @@ -26,6 +26,9 @@ #ifndef MICROPY_INCLUDED_PY_RINGBUF_H #define MICROPY_INCLUDED_PY_RINGBUF_H +#include +#include + typedef struct _ringbuf_t { uint8_t *buf; uint16_t size; @@ -37,7 +40,7 @@ typedef struct _ringbuf_t { // byte buf_array[N]; // ringbuf_t buf = {buf_array, sizeof(buf_array)}; -// Dynamic initialization. This creates root pointer! +// Dynamic initialization. This needs to become findable as a root pointer! #define ringbuf_alloc(r, sz) \ { \ (r)->buf = m_new(uint8_t, sz); \ @@ -69,4 +72,16 @@ static inline int ringbuf_put(ringbuf_t *r, uint8_t v) { return 0; } +static inline size_t ringbuf_free(ringbuf_t *r) { + return (r->size + r->iget - r->iput - 1) % r->size; +} + +static inline size_t ringbuf_avail(ringbuf_t *r) { + return (r->size + r->iput - r->iget) % r->size; +} + +// Note: big-endian. No-op if not enough room available for both bytes. +int ringbuf_get16(ringbuf_t *r); +int ringbuf_put16(ringbuf_t *r, uint16_t v); + #endif // MICROPY_INCLUDED_PY_RINGBUF_H From f67fd95f8d412e1ee17b36861aa12e02c30939fa Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 30 Sep 2019 11:29:52 +1000 Subject: [PATCH 0493/1299] unix/coverage: Add coverage tests for ringbuf. --- ports/unix/coverage.c | 72 ++++++++++++++++++++++++++++++++ tests/unix/extra_coverage.py.exp | 22 ++++++++++ 2 files changed, 94 insertions(+) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 538c32d614a19..b6ebc9fb7eac6 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -10,6 +10,7 @@ #include "py/builtin.h" #include "py/emit.h" #include "py/formatfloat.h" +#include "py/ringbuf.h" #include "py/stream.h" #include "py/binary.h" #include "py/bc.h" @@ -419,6 +420,77 @@ STATIC mp_obj_t extra_coverage(void) { } } + // ringbuf + { + byte buf[100]; + ringbuf_t ringbuf = {buf, sizeof(buf), 0, 0}; + + mp_printf(&mp_plat_print, "# ringbuf\n"); + + // Single-byte put/get with empty ringbuf. + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + ringbuf_put(&ringbuf, 22); + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + mp_printf(&mp_plat_print, "%d\n", ringbuf_get(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + + // Two-byte put/get with empty ringbuf. + ringbuf_put16(&ringbuf, 0xaa55); + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + + // Two-byte put with full ringbuf. + for (int i = 0; i < 99; ++i) { + ringbuf_put(&ringbuf, i); + } + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb)); + // Two-byte put with one byte free. + ringbuf_get(&ringbuf); + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x3377)); + ringbuf_get(&ringbuf); + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0xcc99)); + for (int i = 0; i < 97; ++i) { + ringbuf_get(&ringbuf); + } + mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", ringbuf_free(&ringbuf), ringbuf_avail(&ringbuf)); + + // Two-byte put with wrap around on first byte: + ringbuf.iput = 0; + ringbuf.iget = 0; + for (int i = 0; i < 99; ++i) { + ringbuf_put(&ringbuf, i); + ringbuf_get(&ringbuf); + } + mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb)); + mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); + + // Two-byte put with wrap around on second byte: + ringbuf.iput = 0; + ringbuf.iget = 0; + for (int i = 0; i < 98; ++i) { + ringbuf_put(&ringbuf, i); + ringbuf_get(&ringbuf); + } + mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x22ff)); + mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); + + // Two-byte get from empty ringbuf. + ringbuf.iput = 0; + ringbuf.iget = 0; + mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf)); + + // Two-byte get from ringbuf with one byte available. + ringbuf.iput = 0; + ringbuf.iget = 0; + ringbuf_put(&ringbuf, 0xaa); + mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf)); + } + mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t); s->base.type = &mp_type_stest_fileio; s->buf = NULL; diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 54c5b63e2ba75..8922f96162b84 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -75,6 +75,28 @@ unlocked 1 2 3 +# ringbuf +99 0 +98 1 +22 +99 0 +97 2 +aa55 +99 0 +0 99 +-1 +1 98 +-1 +2 97 +0 +cc99 +99 0 +0 +11bb +0 +22ff +-1 +-1 0123456789 b'0123456789' 7300 7300 From 16f8ceeaaa8262e9483226b18a61da233f257974 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 24 Jul 2019 00:49:06 +1000 Subject: [PATCH 0494/1299] extmod/modbluetooth: Add low-level Python BLE API. --- extmod/modbluetooth.c | 967 ++++++++++++++++++++++++++++++++++++++++++ extmod/modbluetooth.h | 248 +++++++++++ py/mpstate.h | 4 + py/py.mk | 1 + py/runtime.c | 4 + 5 files changed, 1224 insertions(+) create mode 100644 extmod/modbluetooth.c create mode 100644 extmod/modbluetooth.h diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c new file mode 100644 index 0000000000000..f4996f7e881b5 --- /dev/null +++ b/extmod/modbluetooth.c @@ -0,0 +1,967 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Ayke van Laethem + * Copyright (c) 2019 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/binary.h" +#include "py/misc.h" +#include "py/obj.h" +#include "py/objstr.h" +#include "py/objarray.h" +#include "py/qstr.h" +#include "py/runtime.h" +#include "extmod/modbluetooth.h" +#include + +#if MICROPY_PY_BLUETOOTH + +#if !MICROPY_ENABLE_SCHEDULER +#error modbluetooth requires MICROPY_ENABLE_SCHEDULER +#endif + +// This is used to protect the ringbuffer. +#ifndef MICROPY_PY_BLUETOOTH_ENTER +#define MICROPY_PY_BLUETOOTH_ENTER mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); +#define MICROPY_PY_BLUETOOTH_EXIT MICROPY_END_ATOMIC_SECTION(atomic_state); +#endif + +#define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000 + +#define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5 +#define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN (MICROPY_PY_BLUETOOTH_RINGBUF_SIZE / 2) + +STATIC const mp_obj_type_t bluetooth_ble_type; +STATIC const mp_obj_type_t bluetooth_uuid_type; + +typedef struct { + mp_obj_base_t base; + mp_obj_t irq_handler; + mp_obj_t irq_data_tuple; + uint8_t irq_data_bytes[MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN]; + mp_obj_t irq_data_uuid; + uint16_t irq_trigger; + ringbuf_t ringbuf; +} mp_obj_bluetooth_ble_t; + +// TODO: this seems like it could be generic? +STATIC mp_obj_t bluetooth_handle_errno(int err) { + if (err != 0) { + mp_raise_OSError(err); + } + return mp_const_none; +} + +// ---------------------------------------------------------------------------- +// UUID object +// ---------------------------------------------------------------------------- + +// Parse string UUIDs, which are expected to be 128-bit UUIDs. +STATIC void mp_bluetooth_parse_uuid_128bit_str(mp_obj_t obj, uint8_t *uuid) { + size_t str_len; + const char *str_data = mp_obj_str_get_data(obj, &str_len); + int uuid_i = 32; + for (int i = 0; i < str_len; i++) { + char c = str_data[i]; + if (c == '-') { + continue; + } + if (!unichar_isxdigit(c)) { + mp_raise_ValueError("invalid char in UUID"); + } + c = unichar_xdigit_value(c); + uuid_i--; + if (uuid_i < 0) { + mp_raise_ValueError("UUID too long"); + } + if (uuid_i % 2 == 0) { + // lower nibble + uuid[uuid_i/2] |= c; + } else { + // upper nibble + uuid[uuid_i/2] = c << 4; + } + } + if (uuid_i > 0) { + mp_raise_ValueError("UUID too short"); + } +} + +STATIC mp_obj_t bluetooth_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + mp_obj_bluetooth_uuid_t *self = m_new_obj(mp_obj_bluetooth_uuid_t); + self->base.type = &bluetooth_uuid_type; + + if (mp_obj_is_int(all_args[0])) { + self->type = MP_BLUETOOTH_UUID_TYPE_16; + mp_int_t value = mp_obj_get_int(all_args[0]); + if (value > 65535) { + mp_raise_ValueError("invalid UUID"); + } + self->uuid._16 = value; + } else { + self->type = MP_BLUETOOTH_UUID_TYPE_128; + mp_bluetooth_parse_uuid_128bit_str(all_args[0], self->uuid._128); + } + + return self; +} + +STATIC mp_obj_t bluetooth_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); + switch (op) { + case MP_UNARY_OP_HASH: { + if (self->type == MP_BLUETOOTH_UUID_TYPE_16) { + return mp_unary_op(MP_UNARY_OP_HASH, MP_OBJ_NEW_SMALL_INT(self->uuid._16)); + + } else if (self->type == MP_BLUETOOTH_UUID_TYPE_32) { + return mp_unary_op(MP_UNARY_OP_HASH, MP_OBJ_NEW_SMALL_INT(self->uuid._32)); + + } else if (self->type == MP_BLUETOOTH_UUID_TYPE_128) { + return MP_OBJ_NEW_SMALL_INT(qstr_compute_hash(self->uuid._128, sizeof(self->uuid._128))); + } + return MP_OBJ_NULL; + } + default: return MP_OBJ_NULL; // op not supported + } +} + + +STATIC void bluetooth_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->type == MP_BLUETOOTH_UUID_TYPE_16) { + mp_printf(print, "UUID16(0x%04x)", self->uuid._16); + } else if (self->type == MP_BLUETOOTH_UUID_TYPE_32) { + mp_printf(print, "UUID32(0x%08x)", self->uuid._32); + } else if (self->type == MP_BLUETOOTH_UUID_TYPE_128) { + mp_printf(print, "UUID128('"); + for (int i = 0; i < 16; ++i) { + mp_printf(print, "%02x", self->uuid._128[15-i]); + if (i == 3 || i == 5 || i == 7 || i == 9) { + mp_printf(print, "-"); + } + } + mp_printf(print, "')"); + } else { + mp_printf(print, "UUID?(%d)", self->type); + } +} + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +STATIC void ringbuf_put_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { + assert(ringbuf_free(ringbuf) >= uuid->type + 1); + ringbuf_put(ringbuf, uuid->type); + switch (uuid->type) { + case MP_BLUETOOTH_UUID_TYPE_16: + ringbuf_put16(ringbuf, uuid->uuid._16); + break; + case MP_BLUETOOTH_UUID_TYPE_32: + ringbuf_put16(ringbuf, uuid->uuid._32 >> 16); + ringbuf_put16(ringbuf, uuid->uuid._32 & 0xffff); + break; + case MP_BLUETOOTH_UUID_TYPE_128: + for (int i = 0; i < 16; ++i) { + ringbuf_put(ringbuf, uuid->uuid._128[i]); + } + break; + } +} + +STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { + assert(ringbuf_avail(ringbuf) >= 1); + uuid->type = ringbuf_get(ringbuf); + assert(ringbuf_avail(ringbuf) >= uuid->type); + uint16_t h, l; + switch (uuid->type) { + case MP_BLUETOOTH_UUID_TYPE_16: + uuid->uuid._16 = ringbuf_get16(ringbuf); + break; + case MP_BLUETOOTH_UUID_TYPE_32: + h = ringbuf_get16(ringbuf); + l = ringbuf_get16(ringbuf); + uuid->uuid._32 = (h << 16) | l; + break; + case MP_BLUETOOTH_UUID_TYPE_128: + for (int i = 0; i < 16; ++i) { + uuid->uuid._128[i] = ringbuf_get(ringbuf); + } + break; + } +} +#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +STATIC const mp_obj_type_t bluetooth_uuid_type = { + { &mp_type_type }, + .name = MP_QSTR_UUID, + .make_new = bluetooth_uuid_make_new, + .unary_op = bluetooth_uuid_unary_op, + .locals_dict = NULL, + .print = bluetooth_uuid_print, +}; + +// ---------------------------------------------------------------------------- +// Bluetooth object: General +// ---------------------------------------------------------------------------- + +STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + if (MP_STATE_VM(bluetooth) == MP_OBJ_NULL) { + mp_obj_bluetooth_ble_t *o = m_new_obj(mp_obj_bluetooth_ble_t); + o->base.type = &bluetooth_ble_type; + o->irq_handler = mp_const_none; + // Pre-allocated the event data tuple to prevent needing to allocate in the IRQ handler. + o->irq_data_tuple = mp_obj_new_tuple(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN, NULL); + mp_obj_bluetooth_uuid_t *uuid = m_new_obj(mp_obj_bluetooth_uuid_t); + uuid->base.type = &bluetooth_uuid_type; + o->irq_data_uuid = MP_OBJ_FROM_PTR(uuid); + o->irq_trigger = 0; + ringbuf_alloc(&o->ringbuf, MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); + MP_STATE_VM(bluetooth) = MP_OBJ_FROM_PTR(o); + } + return MP_STATE_VM(bluetooth); +} + +STATIC mp_obj_t bluetooth_ble_active(size_t n_args, const mp_obj_t *args) { + if (n_args == 2) { + // Boolean enable/disable argument supplied, set current state. + if (mp_obj_is_true(args[1])) { + int err = mp_bluetooth_init(); + if (err != 0) { + mp_raise_OSError(err); + } + } else { + mp_bluetooth_deinit(); + } + } + // Return current state. + return mp_obj_new_bool(mp_bluetooth_is_enabled()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_active_obj, 1, 2, bluetooth_ble_active); + +STATIC mp_obj_t bluetooth_ble_config(mp_obj_t self_in, mp_obj_t param) { + if (param == MP_OBJ_NEW_QSTR(MP_QSTR_mac)) { + uint8_t addr[6]; + mp_bluetooth_get_device_addr(addr); + return mp_obj_new_bytes(addr, MP_ARRAY_SIZE(addr)); + } else { + mp_raise_ValueError("unknown config param"); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_config_obj, bluetooth_ble_config); + +STATIC mp_obj_t bluetooth_ble_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_handler, ARG_trigger }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_handler, MP_ARG_OBJ|MP_ARG_REQUIRED, {.u_obj = mp_const_none} }, + { MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_BLUETOOTH_IRQ_ALL} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_obj_t callback = args[ARG_handler].u_obj; + if (callback != mp_const_none && !mp_obj_is_callable(callback)) { + mp_raise_ValueError("invalid callback"); + } + + // Update the callback. + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t* bt = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bt->irq_handler = callback; + bt->irq_trigger = args[ARG_trigger].u_int; + MICROPY_PY_BLUETOOTH_EXIT + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_irq_obj, 1, bluetooth_ble_irq); + +// ---------------------------------------------------------------------------- +// Bluetooth object: GAP +// ---------------------------------------------------------------------------- + +STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_interval_ms, ARG_adv_data, ARG_resp_data, ARG_connectable }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_interval_ms, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(100)} }, + { MP_QSTR_adv_data, MP_ARG_OBJ, {.u_obj = mp_const_none } }, + { MP_QSTR_resp_data, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, + { MP_QSTR_connectable, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_true } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t interval_ms; + if (args[ARG_interval_ms].u_obj == mp_const_none || (interval_ms = mp_obj_get_int(args[ARG_interval_ms].u_obj)) == 0) { + mp_bluetooth_gap_advertise_stop(); + return mp_const_none; + } + + bool connectable = mp_obj_is_true(args[ARG_connectable].u_obj); + + mp_buffer_info_t adv_bufinfo = {0}; + if (args[ARG_adv_data].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_adv_data].u_obj, &adv_bufinfo, MP_BUFFER_READ); + } + + mp_buffer_info_t resp_bufinfo = {0}; + if (args[ARG_resp_data].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_resp_data].u_obj, &resp_bufinfo, MP_BUFFER_READ); + } + + return bluetooth_handle_errno(mp_bluetooth_gap_advertise_start(connectable, interval_ms, adv_bufinfo.buf, adv_bufinfo.len, resp_bufinfo.buf, resp_bufinfo.len)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_gap_advertise_obj, 1, bluetooth_ble_gap_advertise); + +STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t characteristics_in, uint16_t **handles, size_t *num_handles) { + if (!mp_obj_is_type(uuid_in, &bluetooth_uuid_type)) { + mp_raise_ValueError("invalid service UUID"); + } + mp_obj_bluetooth_uuid_t *service_uuid = MP_OBJ_TO_PTR(uuid_in); + + mp_obj_t len_in = mp_obj_len(characteristics_in); + size_t len = mp_obj_get_int(len_in); + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(characteristics_in, &iter_buf); + mp_obj_t characteristic_obj; + + // Lists of characteristic uuids and flags. + mp_obj_bluetooth_uuid_t **characteristic_uuids = m_new(mp_obj_bluetooth_uuid_t*, len); + uint8_t *characteristic_flags = m_new(uint8_t, len); + + // Flattened list of descriptor uuids and flags. Grows (realloc) as more descriptors are encountered. + mp_obj_bluetooth_uuid_t **descriptor_uuids = NULL; + uint8_t *descriptor_flags = NULL; + // How many descriptors in the flattened list per characteristic. + uint8_t *num_descriptors = m_new(uint8_t, len); + + // Inititally allocate enough room for the number of characteristics. + // Will be grown to accommodate descriptors as necessary. + *num_handles = len; + *handles = m_new(uint16_t, *num_handles); + + // Extract out characteristic uuids & flags. + + int characteristic_index = 0; // characteristic index. + int handle_index = 0; // handle index. + int descriptor_index = 0; // descriptor index. + while ((characteristic_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + // (uuid, flags, (optional descriptors),) + size_t characteristic_len; + mp_obj_t *characteristic_items; + mp_obj_get_array(characteristic_obj, &characteristic_len, &characteristic_items); + + if (characteristic_len < 2 || characteristic_len > 3) { + mp_raise_ValueError("invalid characteristic tuple"); + } + mp_obj_t uuid_obj = characteristic_items[0]; + if (!mp_obj_is_type(uuid_obj, &bluetooth_uuid_type)) { + mp_raise_ValueError("invalid characteristic UUID"); + } + + (*handles)[handle_index++] = 0xffff; + + // Optional third element, iterable of descriptors. + if (characteristic_len >= 3) { + mp_obj_t descriptors_len_in = mp_obj_len(characteristic_items[2]); + num_descriptors[characteristic_index] = mp_obj_get_int(descriptors_len_in); + + if (num_descriptors[characteristic_index] == 0) { + continue; + } + + // Grow the flattened uuids and flags arrays with this many more descriptors. + descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t*, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); + descriptor_flags = m_renew(uint8_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]); + + // Also grow the handles array. + *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]); + + mp_obj_iter_buf_t iter_buf_desc; + mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc); + mp_obj_t descriptor_obj; + + // Extract out descriptors for this characteristic. + while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) { + // (uuid, flags,) + mp_obj_t *descriptor_items; + mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items); + mp_obj_t desc_uuid_obj = descriptor_items[0]; + if (!mp_obj_is_type(desc_uuid_obj, &bluetooth_uuid_type)) { + mp_raise_ValueError("invalid descriptor UUID"); + } + + descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj); + descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]); + ++descriptor_index; + + (*handles)[handle_index++] = 0xffff; + } + + // Reflect that we've grown the handles array. + *num_handles += num_descriptors[characteristic_index]; + } + + characteristic_uuids[characteristic_index] = MP_OBJ_TO_PTR(uuid_obj); + characteristic_flags[characteristic_index] = mp_obj_get_int(characteristic_items[1]); + ++characteristic_index; + } + + // Add service. + return mp_bluetooth_gatts_register_service(service_uuid, characteristic_uuids, characteristic_flags, descriptor_uuids, descriptor_flags, num_descriptors, *handles, len); +} + +STATIC mp_obj_t bluetooth_ble_gatts_register_services(mp_obj_t self_in, mp_obj_t services_in) { + mp_obj_t len_in = mp_obj_len(services_in); + size_t len = mp_obj_get_int(len_in); + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(services_in, &iter_buf); + mp_obj_t service_tuple_obj; + + mp_obj_tuple_t *result = mp_obj_new_tuple(len, NULL); + + uint16_t **handles = m_new0(uint16_t*, len); + size_t *num_handles = m_new0(size_t, len); + + // We always reset the service list, as Nimble has no other option. + // TODO: Add a `reset` or `clear` kwarg (defaulting to True) to make this behavior optional. + int err = mp_bluetooth_gatts_register_service_begin(true); + if (err != 0) { + return bluetooth_handle_errno(err); + } + + int i = 0; + while ((service_tuple_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + // (uuid, chars) + mp_obj_t *service_items; + mp_obj_get_array_fixed_n(service_tuple_obj, 2, &service_items); + err = bluetooth_gatts_register_service(service_items[0], service_items[1], &handles[i], &num_handles[i]); + if (err != 0) { + return bluetooth_handle_errno(err); + } + + ++i; + } + + // On Nimble, this will actually perform the registration, making the handles valid. + err = mp_bluetooth_gatts_register_service_end(); + if (err != 0) { + return bluetooth_handle_errno(err); + } + + // Return tuple of tuple of value handles. + // TODO: Also the Generic Access service characteristics? + for (i = 0; i < len; ++i) { + mp_obj_tuple_t *service_handles = mp_obj_new_tuple(num_handles[i], NULL); + for (int j = 0; j < num_handles[i]; ++j) { + service_handles->items[j] = MP_OBJ_NEW_SMALL_INT(handles[i][j]); + } + result->items[i] = MP_OBJ_FROM_PTR(service_handles); + } + return MP_OBJ_FROM_PTR(result); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gatts_register_services_obj, bluetooth_ble_gatts_register_services); + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) { + uint8_t addr_type = mp_obj_get_int(args[1]); + mp_buffer_info_t bufinfo = {0}; + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + if (bufinfo.len != 6) { + mp_raise_ValueError("invalid addr"); + } + mp_int_t scan_duration_ms = MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS; + if (n_args == 4) { + scan_duration_ms = mp_obj_get_int(args[3]); + } + + int err = mp_bluetooth_gap_peripheral_connect(addr_type, bufinfo.buf, scan_duration_ms); + return bluetooth_handle_errno(err); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 4, bluetooth_ble_gap_connect); + +STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) { + if (n_args == 2 && args[1] == mp_const_none) { + int err = mp_bluetooth_gap_scan_stop(); + return bluetooth_handle_errno(err); + } else { + mp_int_t duration_ms = 0; + if (n_args == 2) { + if (!mp_obj_is_int(args[1])) { + mp_raise_ValueError("invalid duration"); + } + duration_ms = mp_obj_get_int(args[1]); + } + + int err = mp_bluetooth_gap_scan_start(duration_ms); + return bluetooth_handle_errno(err); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_scan_obj, 1, 2, bluetooth_ble_gap_scan); +#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +STATIC mp_obj_t bluetooth_ble_gap_disconnect(mp_obj_t self_in, mp_obj_t conn_handle_in) { + uint16_t conn_handle = mp_obj_get_int(conn_handle_in); + int err = mp_bluetooth_gap_disconnect(conn_handle); + return bluetooth_handle_errno(err); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gap_disconnect_obj, bluetooth_ble_gap_disconnect); + +// ---------------------------------------------------------------------------- +// Bluetooth object: GATTS (Peripheral/Advertiser role) +// ---------------------------------------------------------------------------- + +STATIC mp_obj_t bluetooth_ble_gatts_read(mp_obj_t self_in, mp_obj_t value_handle_in) { + size_t len = 0; + uint8_t* buf; + mp_bluetooth_gatts_read(mp_obj_get_int(value_handle_in), &buf, &len); + return mp_obj_new_bytes(buf, len); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gatts_read_obj, bluetooth_ble_gatts_read); + +STATIC mp_obj_t bluetooth_ble_gatts_write(mp_obj_t self_in, mp_obj_t value_handle_in, mp_obj_t data) { + mp_buffer_info_t bufinfo = {0}; + mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); + int err = mp_bluetooth_gatts_write(mp_obj_get_int(value_handle_in), bufinfo.buf, bufinfo.len); + if (err != 0) { + mp_raise_OSError(err); + } + return MP_OBJ_NEW_SMALL_INT(bufinfo.len); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(bluetooth_ble_gatts_write_obj, bluetooth_ble_gatts_write); + +STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) { + mp_int_t conn_handle = mp_obj_get_int(args[1]); + mp_int_t value_handle = mp_obj_get_int(args[2]); + + if (n_args == 4) { + mp_buffer_info_t bufinfo = {0}; + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + size_t len = bufinfo.len; + int err = mp_bluetooth_gatts_notify_send(conn_handle, value_handle, bufinfo.buf, &len); + if (err != 0) { + mp_raise_OSError(err); + } + return MP_OBJ_NEW_SMALL_INT(len); + } else { + int err = mp_bluetooth_gatts_notify(conn_handle, value_handle); + return bluetooth_handle_errno(err); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify); + +// ---------------------------------------------------------------------------- +// Bluetooth object: GATTC (Central/Scanner role) +// ---------------------------------------------------------------------------- + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +STATIC mp_obj_t bluetooth_ble_gattc_discover_services(mp_obj_t self_in, mp_obj_t conn_handle_in) { + mp_int_t conn_handle = mp_obj_get_int(conn_handle_in); + return bluetooth_handle_errno(mp_bluetooth_gattc_discover_primary_services(conn_handle)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gattc_discover_services_obj, bluetooth_ble_gattc_discover_services); + +STATIC mp_obj_t bluetooth_ble_gattc_discover_characteristics(size_t n_args, const mp_obj_t *args) { + mp_int_t conn_handle = mp_obj_get_int(args[1]); + mp_int_t start_handle = mp_obj_get_int(args[2]); + mp_int_t end_handle = mp_obj_get_int(args[3]); + return bluetooth_handle_errno(mp_bluetooth_gattc_discover_characteristics(conn_handle, start_handle, end_handle)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_discover_characteristics_obj, 4, 4, bluetooth_ble_gattc_discover_characteristics); + +STATIC mp_obj_t bluetooth_ble_gattc_discover_descriptors(size_t n_args, const mp_obj_t *args) { + mp_int_t conn_handle = mp_obj_get_int(args[1]); + mp_int_t start_handle = mp_obj_get_int(args[2]); + mp_int_t end_handle = mp_obj_get_int(args[3]); + return bluetooth_handle_errno(mp_bluetooth_gattc_discover_descriptors(conn_handle, start_handle, end_handle)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_discover_descriptors_obj, 4, 4, bluetooth_ble_gattc_discover_descriptors); + +STATIC mp_obj_t bluetooth_ble_gattc_read(mp_obj_t self_in, mp_obj_t conn_handle_in, mp_obj_t value_handle_in) { + mp_int_t conn_handle = mp_obj_get_int(conn_handle_in); + mp_int_t value_handle = mp_obj_get_int(value_handle_in); + return bluetooth_handle_errno(mp_bluetooth_gattc_read(conn_handle, value_handle)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(bluetooth_ble_gattc_read_obj, bluetooth_ble_gattc_read); + +STATIC mp_obj_t bluetooth_ble_gattc_write(size_t n_args, const mp_obj_t *args) { + mp_int_t conn_handle = mp_obj_get_int(args[1]); + mp_int_t value_handle = mp_obj_get_int(args[2]); + mp_obj_t data = args[3]; + mp_buffer_info_t bufinfo = {0}; + mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); + size_t len = bufinfo.len; + return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, &len)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_write_obj, 4, 4, bluetooth_ble_gattc_write); + +#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +// ---------------------------------------------------------------------------- +// Bluetooth object: Definition +// ---------------------------------------------------------------------------- + +STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = { + // General + { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&bluetooth_ble_active_obj) }, + { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&bluetooth_ble_config_obj) }, + { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&bluetooth_ble_irq_obj) }, + // GAP + { MP_ROM_QSTR(MP_QSTR_gap_advertise), MP_ROM_PTR(&bluetooth_ble_gap_advertise_obj) }, + #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + { MP_ROM_QSTR(MP_QSTR_gap_connect), MP_ROM_PTR(&bluetooth_ble_gap_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_gap_scan), MP_ROM_PTR(&bluetooth_ble_gap_scan_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_gap_disconnect), MP_ROM_PTR(&bluetooth_ble_gap_disconnect_obj) }, + // GATT Server (i.e. peripheral/advertiser role) + { MP_ROM_QSTR(MP_QSTR_gatts_register_services), MP_ROM_PTR(&bluetooth_ble_gatts_register_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_gatts_read), MP_ROM_PTR(&bluetooth_ble_gatts_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_gatts_write), MP_ROM_PTR(&bluetooth_ble_gatts_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_gatts_notify), MP_ROM_PTR(&bluetooth_ble_gatts_notify_obj) }, + #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + // GATT Client (i.e. central/scanner role) + { MP_ROM_QSTR(MP_QSTR_gattc_discover_services), MP_ROM_PTR(&bluetooth_ble_gattc_discover_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_gattc_discover_characteristics), MP_ROM_PTR(&bluetooth_ble_gattc_discover_characteristics_obj) }, + { MP_ROM_QSTR(MP_QSTR_gattc_discover_descriptors), MP_ROM_PTR(&bluetooth_ble_gattc_discover_descriptors_obj) }, + { MP_ROM_QSTR(MP_QSTR_gattc_read), MP_ROM_PTR(&bluetooth_ble_gattc_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_gattc_write), MP_ROM_PTR(&bluetooth_ble_gattc_write_obj) }, + #endif +}; +STATIC MP_DEFINE_CONST_DICT(bluetooth_ble_locals_dict, bluetooth_ble_locals_dict_table); + +STATIC const mp_obj_type_t bluetooth_ble_type = { + { &mp_type_type }, + .name = MP_QSTR_BLE, + .make_new = bluetooth_ble_make_new, + .locals_dict = (void*)&bluetooth_ble_locals_dict, +}; + +STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bluetooth) }, + { MP_ROM_QSTR(MP_QSTR_BLE), MP_ROM_PTR(&bluetooth_ble_type) }, + { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bluetooth_uuid_type) }, + { MP_ROM_QSTR(MP_QSTR_FLAG_READ), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) }, + { MP_ROM_QSTR(MP_QSTR_FLAG_WRITE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_FLAG_NOTIFY), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_bluetooth_globals, mp_module_bluetooth_globals_table); + +const mp_obj_module_t mp_module_bluetooth = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_bluetooth_globals, +}; + +// Helpers + +#include + +STATIC void ringbuf_extract(ringbuf_t* ringbuf, mp_obj_tuple_t *data_tuple, size_t n_u16, size_t n_u8, mp_obj_str_t *bytes_addr, size_t n_b, size_t n_i8, mp_obj_bluetooth_uuid_t *uuid, mp_obj_str_t *bytes_data) { + assert(ringbuf_avail(ringbuf) >= n_u16 * 2 + n_u8 + (bytes_addr ? 6 : 0) + n_b + n_i8 + (uuid ? 1 : 0) + (bytes_data ? 1 : 0)); + int j = 0; + + for (int i = 0; i < n_u16; ++i) { + data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT(ringbuf_get16(ringbuf)); + } + if (n_u8) { + data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT(ringbuf_get(ringbuf)); + } + if (bytes_addr) { + bytes_addr->len = 6; + for (int i = 0; i < bytes_addr->len; ++i) { + // cast away const, this is actually bt->irq_data_bytes. + ((uint8_t*)bytes_addr->data)[i] = ringbuf_get(ringbuf); + } + data_tuple->items[j++] = MP_OBJ_FROM_PTR(bytes_addr); + } + if (n_b) { + data_tuple->items[j++] = mp_obj_new_bool(ringbuf_get(ringbuf)); + } + if (n_i8) { + // Note the int8_t got packed into the ringbuf as a uint8_t. + data_tuple->items[j++] = MP_OBJ_NEW_SMALL_INT((int8_t)ringbuf_get(ringbuf)); + } + if (uuid) { + ringbuf_get_uuid(ringbuf, uuid); + data_tuple->items[j++] = MP_OBJ_FROM_PTR(uuid); + } + // The code that enqueues into the ringbuf should ensure that it doesn't + // put more than MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN bytes into + // the ringbuf. + if (bytes_data) { + bytes_data->len = ringbuf_get(ringbuf); + for (int i = 0; i < bytes_data->len; ++i) { + // cast away const, this is actually bt->irq_data_bytes + 6. + ((uint8_t*)bytes_data->data)[i] = ringbuf_get(ringbuf); + } + data_tuple->items[j++] = MP_OBJ_FROM_PTR(bytes_data); + } + + data_tuple->len = j; +} + +STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) { + // This is always executing in schedule context. + for (;;) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + + mp_int_t event = event = ringbuf_get16(&o->ringbuf); + if (event < 0) { + // Nothing available in ringbuf. + MICROPY_PY_BLUETOOTH_EXIT + break; + } + + // Although we're in schedule context, this code still avoids using any allocations: + // - IRQs are disabled (to protect the ringbuf), and we need to avoid triggering GC + // - The user's handler might not alloc, so we shouldn't either. + + mp_obj_t handler = handler = o->irq_handler; + mp_obj_tuple_t *data_tuple = MP_OBJ_TO_PTR(o->irq_data_tuple); + + // Some events need to pass bytes objects to their handler, using the + // pre-allocated bytes array. + mp_obj_str_t irq_data_bytes_addr = {{&mp_type_bytes}, 0, 6, o->irq_data_bytes}; + mp_obj_str_t irq_data_bytes_data = {{&mp_type_bytes}, 0, 0, o->irq_data_bytes + 6}; + + if (event == MP_BLUETOOTH_IRQ_CENTRAL_CONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT || event == MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT) { + // conn_handle, addr_type, addr + ringbuf_extract(&o->ringbuf, data_tuple, 1, 1, &irq_data_bytes_addr, 0, 0, NULL, NULL); + } else if (event == MP_BLUETOOTH_IRQ_GATTS_WRITE) { + // conn_handle, value_handle + ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, NULL, NULL); + #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + } else if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT) { + // addr_type, addr, connectable, rssi, adv_data + ringbuf_extract(&o->ringbuf, data_tuple, 0, 1, &irq_data_bytes_addr, 1, 1, NULL, &irq_data_bytes_data); + } else if (event == MP_BLUETOOTH_IRQ_SCAN_COMPLETE) { + // No params required. + data_tuple->len = 0; + } else if (event == MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT) { + // conn_handle, start_handle, end_handle, uuid + ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, 0, MP_OBJ_TO_PTR(o->irq_data_uuid), NULL); + } else if (event == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT) { + // conn_handle, def_handle, value_handle, properties, uuid + ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, 0, MP_OBJ_TO_PTR(o->irq_data_uuid), NULL); + } else if (event == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT) { + // conn_handle, handle, uuid + ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, MP_OBJ_TO_PTR(o->irq_data_uuid), NULL); + } else if (event == MP_BLUETOOTH_IRQ_GATTC_READ_RESULT || event == MP_BLUETOOTH_IRQ_GATTC_NOTIFY || event == MP_BLUETOOTH_IRQ_GATTC_INDICATE) { + // conn_handle, value_handle, data + ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, NULL, &irq_data_bytes_data); + } else if (event == MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS) { + // conn_handle, value_handle, status + ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, 0, NULL, NULL); + #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + } + + MICROPY_PY_BLUETOOTH_EXIT + + mp_call_function_2(handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple)); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_invoke_irq); + +// ---------------------------------------------------------------------------- +// Port API +// ---------------------------------------------------------------------------- + +// Callbacks are called in interrupt context (i.e. can't allocate), so we need to push the data +// into the ringbuf and schedule the callback via mp_sched_schedule. + +STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event, bool *sched) { + *sched = false; + + if (ringbuf_free(&o->ringbuf) >= len + 2 && (o->irq_trigger & event) && o->irq_handler != mp_const_none) { + *sched = ringbuf_avail(&o->ringbuf) == 0; + ringbuf_put16(&o->ringbuf, event); + return true; + } else { + return false; + } +} + +STATIC void schedule_ringbuf(bool sched) { + if (sched) { + mp_sched_schedule(MP_OBJ_FROM_PTR(MP_ROM_PTR(&bluetooth_ble_invoke_irq_obj)), mp_const_none); + } +} + +void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 9, event, &sched)) { + ringbuf_put16(&o->ringbuf, conn_handle); + ringbuf_put(&o->ringbuf, addr_type); + for (int i = 0; i < 6; ++i) { + ringbuf_put(&o->ringbuf, addr[i]); + } + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +void mp_bluetooth_gatts_on_write(uint16_t value_handle, uint16_t conn_handle) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 4, MP_BLUETOOTH_IRQ_GATTS_WRITE, &sched)) { + ringbuf_put16(&o->ringbuf, conn_handle); + ringbuf_put16(&o->ringbuf, value_handle); + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +void mp_bluetooth_gap_on_scan_complete(void) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 0, MP_BLUETOOTH_IRQ_SCAN_COMPLETE, &sched)) { + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, bool connectable, const int8_t rssi, const uint8_t *data, size_t data_len) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 1 + 6 + 1 + 1 + data_len, MP_BLUETOOTH_IRQ_SCAN_RESULT, &sched)) { + ringbuf_put(&o->ringbuf, addr_type); + for (int i = 0; i < 6; ++i) { + ringbuf_put(&o->ringbuf, addr[i]); + } + ringbuf_put(&o->ringbuf, connectable ? 1 : 0); + // Note conversion of int8_t rssi to uint8_t. Must un-convert on the way out. + ringbuf_put(&o->ringbuf, (uint8_t)rssi); + data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); + ringbuf_put(&o->ringbuf, data_len); + for (int i = 0; i < data_len; ++i) { + ringbuf_put(&o->ringbuf, data[i]); + } + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 2 + 2 + 2 + 1 + service_uuid->type, MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, &sched)) { + ringbuf_put16(&o->ringbuf, conn_handle); + ringbuf_put16(&o->ringbuf, start_handle); + ringbuf_put16(&o->ringbuf, end_handle); + ringbuf_put_uuid(&o->ringbuf, service_uuid); + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, &sched)) { + ringbuf_put16(&o->ringbuf, conn_handle); + ringbuf_put16(&o->ringbuf, def_handle); + ringbuf_put16(&o->ringbuf, value_handle); + ringbuf_put(&o->ringbuf, properties); + ringbuf_put_uuid(&o->ringbuf, characteristic_uuid); + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 2 + 2 + 1 + descriptor_uuid->type, MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT, &sched)) { + ringbuf_put16(&o->ringbuf, conn_handle); + ringbuf_put16(&o->ringbuf, handle); + ringbuf_put_uuid(&o->ringbuf, descriptor_uuid); + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t *data, size_t data_len) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 2 + 2 + 1 + data_len, event, &sched)) { + ringbuf_put16(&o->ringbuf, conn_handle); + ringbuf_put16(&o->ringbuf, value_handle); + data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); + ringbuf_put(&o->ringbuf, data_len); + for (int i = 0; i < data_len; ++i) { + ringbuf_put(&o->ringbuf, data[i]); + } + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status) { + MICROPY_PY_BLUETOOTH_ENTER + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + bool sched; + if (enqueue_irq(o, 2 + 2 + 2, MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS, &sched)) { + ringbuf_put16(&o->ringbuf, conn_handle); + ringbuf_put16(&o->ringbuf, value_handle); + ringbuf_put16(&o->ringbuf, status); + } + MICROPY_PY_BLUETOOTH_EXIT + schedule_ringbuf(sched); +} + +#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +#if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK +bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + if ((o->irq_trigger & MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST) && o->irq_handler != mp_const_none) { + // Use pre-allocated tuple because this is a hard IRQ. + mp_obj_tuple_t *data = MP_OBJ_FROM_PTR(o->irq_data_tuple); + data->items[0] = MP_OBJ_NEW_SMALL_INT(conn_handle); + data->items[1] = MP_OBJ_NEW_SMALL_INT(value_handle); + data->len = 2; + mp_obj_t irq_ret = mp_call_function_2_protected(o->irq_handler, MP_OBJ_NEW_SMALL_INT(MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST), o->irq_data_tuple); + // If the IRQ handler explicitly returned false, then deny the read. Otherwise if it returns None/True, allow it. + return irq_ret != MP_OBJ_NULL && (irq_ret == mp_const_none || mp_obj_is_true(irq_ret)); + } else { + // No IRQ handler, allow the read. + return true; + } +} +#endif + +#endif // MICROPY_PY_BLUETOOTH diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h new file mode 100644 index 0000000000000..1b1318dec5380 --- /dev/null +++ b/extmod/modbluetooth.h @@ -0,0 +1,248 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Ayke van Laethem + * Copyright (c) 2019 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_H +#define MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_H + +#include + +#include "py/obj.h" +#include "py/objlist.h" +#include "py/ringbuf.h" + +// Port specific configuration. +#ifndef MICROPY_PY_BLUETOOTH_RINGBUF_SIZE +#define MICROPY_PY_BLUETOOTH_RINGBUF_SIZE (128) +#endif + +#ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (0) +#endif + +#ifndef MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK +#define MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK (0) +#endif + +// Common constants. +#define MP_BLUETOOTH_MAX_ATTR_SIZE (20) + +// Advertisement packet lengths +#define MP_BLUETOOTH_GAP_ADV_MAX_LEN (32) + +#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ (1 << 1) +#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (1 << 3) +#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (1 << 4) + +// Type value also doubles as length. +#define MP_BLUETOOTH_UUID_TYPE_16 (2) +#define MP_BLUETOOTH_UUID_TYPE_32 (4) +#define MP_BLUETOOTH_UUID_TYPE_128 (16) + +// Address types (for the addr_type params). +// Ports will need to map these to their own values. +#define MP_BLUETOOTH_ADDR_PUBLIC (0x00) // Public (identity) address. (Same as NimBLE and NRF SD) +#define MP_BLUETOOTH_ADDR_RANDOM_STATIC (0x01) // Random static (identity) address. (Same as NimBLE and NRF SD) +#define MP_BLUETOOTH_ADDR_PUBLIC_ID (0x02) // (Same as NimBLE) +#define MP_BLUETOOTH_ADDR_RANDOM_ID (0x03) // (Same as NimBLE) +#define MP_BLUETOOTH_ADDR_RANDOM_PRIVATE_RESOLVABLE (0x12) // Random private resolvable address. (NRF SD 0x02) +#define MP_BLUETOOTH_ADDR_RANDOM_PRIVATE_NON_RESOLVABLE (0x13) // Random private non-resolvable address. (NRF SD 0x03) + +// Event codes for the IRQ handler. +// Can also be combined to pass to the trigger param to select which events you +// are interested in. +// Note this is currently stored in a uint16_t (in irq_trigger, and the event +// arg to the irq handler), so one spare value remaining. +#define MP_BLUETOOTH_IRQ_CENTRAL_CONNECT (1 << 0) +#define MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT (1 << 1) +#define MP_BLUETOOTH_IRQ_GATTS_WRITE (1 << 2) +#define MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST (1 << 3) +#define MP_BLUETOOTH_IRQ_SCAN_RESULT (1 << 4) +#define MP_BLUETOOTH_IRQ_SCAN_COMPLETE (1 << 5) +#define MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT (1 << 6) +#define MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT (1 << 7) +#define MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT (1 << 8) +#define MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT (1 << 9) +#define MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT (1 << 10) +#define MP_BLUETOOTH_IRQ_GATTC_READ_RESULT (1 << 11) +#define MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS (1 << 12) +#define MP_BLUETOOTH_IRQ_GATTC_NOTIFY (1 << 13) +#define MP_BLUETOOTH_IRQ_GATTC_INDICATE (1 << 14) +#define MP_BLUETOOTH_IRQ_ALL (0xffff) + +/* +These aren't included in the module for space reasons, but can be used +in your Python code if necessary. + +from micropython import const +_IRQ_CENTRAL_CONNECT = const(1 << 0) +_IRQ_CENTRAL_DISCONNECT = const(1 << 1) +_IRQ_GATTS_WRITE = const(1 << 2) +_IRQ_GATTS_READ_REQUEST = const(1 << 3) +_IRQ_SCAN_RESULT = const(1 << 4) +_IRQ_SCAN_COMPLETE = const(1 << 5) +_IRQ_PERIPHERAL_CONNECT = const(1 << 6) +_IRQ_PERIPHERAL_DISCONNECT = const(1 << 7) +_IRQ_GATTC_SERVICE_RESULT = const(1 << 8) +_IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9) +_IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10) +_IRQ_GATTC_READ_RESULT = const(1 << 11) +_IRQ_GATTC_WRITE_STATUS = const(1 << 12) +_IRQ_GATTC_NOTIFY = const(1 << 13) +_IRQ_GATTC_INDICATE = const(1 << 14) +_IRQ_ALL = const(0xffff) +*/ + +// Common UUID type. +// Ports are expected to map this to their own internal UUID types. +typedef struct { + mp_obj_base_t base; + uint8_t type; + union { + uint16_t _16; + uint32_t _32; + uint8_t _128[16]; + } uuid; +} mp_obj_bluetooth_uuid_t; + +////////////////////////////////////////////////////////////// +// API implemented by ports (i.e. called from modbluetooth.c): + +// TODO: At the moment this only allows for a single `Bluetooth` instance to be created. +// Ideally in the future we'd be able to have multiple instances or to select a specific BT driver or HCI UART. +// So these global methods should be replaced with a struct of function pointers (like the machine.I2C implementations). + +// Any method returning an int returns errno on failure, otherwise zero. + +// Note: All methods dealing with addresses (as 6-byte uint8 pointers) are in big-endian format. +// (i.e. the same way they would be printed on a device sticker or in a UI). +// This means that the lower level implementation might need to reorder them (e.g. Nimble works in little-endian) + +// Enables the Bluetooth stack. +int mp_bluetooth_init(void); + +// Disables the Bluetooth stack. Is a no-op when not enabled. +void mp_bluetooth_deinit(void); + +// Returns true when the Bluetooth stack is enabled. +bool mp_bluetooth_is_enabled(void); + +// Gets the MAC addr of this device in big-endian format. +void mp_bluetooth_get_device_addr(uint8_t *addr); + +// Start advertisement. Will re-start advertisement when already enabled. +// Returns errno on failure. +int mp_bluetooth_gap_advertise_start(bool connectable, uint16_t interval_ms, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len); + +// Stop advertisement. No-op when already stopped. +void mp_bluetooth_gap_advertise_stop(void); + +// Start adding services. Must be called before mp_bluetooth_register_service. +int mp_bluetooth_gatts_register_service_begin(bool reset); +// // Add a service with the given list of characteristics to the queue to be registered. +// The value_handles won't be valid until after mp_bluetooth_register_service_end is called. +int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics); +// Register any queued services. +int mp_bluetooth_gatts_register_service_end(); + +// Read the value from the local gatts db (likely this has been written by a central). +int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len); +// Write a value to the local gatts db (ready to be queried by a central). +int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len); +// Notify the central that it should do a read. +int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle); +// Notify the central, including a data payload. (Note: does not set the gatts db value). +int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len); +// Indicate the central. +int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle); + +// Disconnect from a central or peripheral. +int mp_bluetooth_gap_disconnect(uint16_t conn_handle); + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +// Start a discovery (scan). Set duration to zero to run continuously. +int mp_bluetooth_gap_scan_start(int32_t duration_ms); + +// Stop discovery (if currently active). +int mp_bluetooth_gap_scan_stop(void); + +// Connect to a found peripheral. +int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms); + +// Find all primary services on the connected peripheral. +int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle); + +// Find all characteristics on the specified service on a connected peripheral. +int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle); + +// Find all descriptors on the specified characteristic on a connected peripheral. +int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle); + +// Initiate read of a value from the remote peripheral. +int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle); + +// Write the value to the remote peripheral. +int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len); +#endif + +///////////////////////////////////////////////////////////////////////////// +// API implemented by modbluetooth (called by port-specific implementations): + +// Notify modbluetooth that a connection/disconnection event has occurred. +void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr); + +// Call this when a characteristic is written to. +void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle); + +#if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK +// Call this when a characteristic is read from. Return false to deny the read. +bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle); +#endif + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +// Notify modbluetooth that scan has finished, either timeout, manually, or by some other action (e.g. connecting). +void mp_bluetooth_gap_on_scan_complete(void); + +// Notify modbluetooth of a scan result. +void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, bool connectable, const int8_t rssi, const uint8_t *data, size_t data_len); + +// Notify modbluetooth that a service was found (either by discover-all, or discover-by-uuid). +void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid); + +// Notify modbluetooth that a characteristic was found (either by discover-all-on-service, or discover-by-uuid-on-service). +void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid); + +// Notify modbluetooth that a descriptor was found. +void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid); + +// Notify modbluetooth that a read has completed with data (or notify/indicate data available, use `event` to disambiguate). +void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t *data, size_t data_len); + +// Notify modbluetooth that a write has completed. +void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status); +#endif + +#endif // MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_H diff --git a/py/mpstate.h b/py/mpstate.h index 0f9c56d2c7004..ab7d8c51b95bc 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -189,6 +189,10 @@ typedef struct _mp_state_vm_t { struct _mp_vfs_mount_t *vfs_mount_table; #endif + #if MICROPY_PY_BLUETOOTH + mp_obj_t bluetooth; + #endif + // // END ROOT POINTER SECTION //////////////////////////////////////////////////////////// diff --git a/py/py.mk b/py/py.mk index d30ee81bc1fbe..ba3a8639bf61a 100644 --- a/py/py.mk +++ b/py/py.mk @@ -174,6 +174,7 @@ PY_EXTMOD_O_BASENAME = \ extmod/machine_pulse.o \ extmod/machine_i2c.o \ extmod/machine_spi.o \ + extmod/modbluetooth.o \ extmod/modussl_axtls.o \ extmod/modussl_mbedtls.o \ extmod/modurandom.o \ diff --git a/py/runtime.c b/py/runtime.c index ecbdff2bab6e8..2657e7cc2588d 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -131,6 +131,10 @@ void mp_init(void) { MP_STATE_THREAD(current_code_state) = NULL; #endif + #if MICROPY_PY_BLUETOOTH + MP_STATE_VM(bluetooth) = MP_OBJ_NULL; + #endif + #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif From 497dae45e713921bb8b017e92657eaa0dcd6f0fd Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sun, 29 Sep 2019 23:05:15 +1000 Subject: [PATCH 0495/1299] extmod/modbluetooth_nimble: Implement modbluetooth API with Nimble. --- extmod/modbluetooth_nimble.c | 854 +++++++++++++++++++++++++++++++++++ 1 file changed, 854 insertions(+) create mode 100644 extmod/modbluetooth_nimble.c diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c new file mode 100644 index 0000000000000..3a6d1cba43d35 --- /dev/null +++ b/extmod/modbluetooth_nimble.c @@ -0,0 +1,854 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * Copyright (c) 2019 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "systick.h" +#include "pendsv.h" + +#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE + +#ifndef MICROPY_PY_BLUETOOTH_DEFAULT_NAME +#define MICROPY_PY_BLUETOOTH_DEFAULT_NAME "PYBD" +#endif + +#include "extmod/modbluetooth.h" + +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "nimble/ble.h" +#include "nimble/nimble_port.h" +#include "services/gap/ble_svc_gap.h" +#include "transport/uart/ble_hci_uart.h" + +#define DEBUG_MALLOC_printf(...) //printf(__VA_ARGS__) +#define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__) + +STATIC int8_t ble_hs_err_to_errno_table[] = { + [BLE_HS_EAGAIN] = MP_EAGAIN, + [BLE_HS_EALREADY] = MP_EALREADY, + [BLE_HS_EINVAL] = MP_EINVAL, + [BLE_HS_EMSGSIZE] = MP_EIO, + [BLE_HS_ENOENT] = MP_ENOENT, + [BLE_HS_ENOMEM] = MP_ENOMEM, + [BLE_HS_ENOTCONN] = MP_ENOTCONN, + [BLE_HS_ENOTSUP] = MP_EOPNOTSUPP, + [BLE_HS_EAPP] = MP_EIO, + [BLE_HS_EBADDATA] = MP_EIO, + [BLE_HS_EOS] = MP_EIO, + [BLE_HS_ECONTROLLER] = MP_EIO, + [BLE_HS_ETIMEOUT] = MP_ETIMEDOUT, + [BLE_HS_EDONE] = MP_EIO, // TODO: Maybe should be MP_EISCONN (connect uses this for "already connected"). + [BLE_HS_EBUSY] = MP_EBUSY, + [BLE_HS_EREJECT] = MP_EIO, + [BLE_HS_EUNKNOWN] = MP_EIO, + [BLE_HS_EROLE] = MP_EIO, + [BLE_HS_ETIMEOUT_HCI] = MP_EIO, + [BLE_HS_ENOMEM_EVT] = MP_EIO, + [BLE_HS_ENOADDR] = MP_EIO, + [BLE_HS_ENOTSYNCED] = MP_EIO, + [BLE_HS_EAUTHEN] = MP_EIO, + [BLE_HS_EAUTHOR] = MP_EIO, + [BLE_HS_EENCRYPT] = MP_EIO, + [BLE_HS_EENCRYPT_KEY_SZ] = MP_EIO, + [BLE_HS_ESTORE_CAP] = MP_EIO, + [BLE_HS_ESTORE_FAIL] = MP_EIO, + [BLE_HS_EPREEMPTED] = MP_EIO, + [BLE_HS_EDISABLED] = MP_EIO, +}; + +STATIC int ble_hs_err_to_errno(int err) { + if (0 <= err && err < MP_ARRAY_SIZE(ble_hs_err_to_errno_table)) { + return ble_hs_err_to_errno_table[err]; + } else { + return MP_EIO; + } +} + +// Maintain a linked list of heap memory that we've passed to Nimble, +// discoverable via the bluetooth_nimble_memory root pointer. + +// MP_STATE_PORT(bluetooth_nimble_memory) is a pointer to [next, prev, data...]. + +// TODO: This is duplicated from mbedtls. Perhaps make this a generic feature? +void *m_malloc_bluetooth(size_t size) { + void **ptr = m_malloc0(size + 2 * sizeof(uintptr_t)); + if (MP_STATE_PORT(bluetooth_nimble_memory) != NULL) { + MP_STATE_PORT(bluetooth_nimble_memory)[0] = ptr; + } + ptr[0] = NULL; + ptr[1] = MP_STATE_PORT(bluetooth_nimble_memory); + MP_STATE_PORT(bluetooth_nimble_memory) = ptr; + return &ptr[2]; +} + +#define m_new_bluetooth(type, num) ((type*)m_malloc_bluetooth(sizeof(type) * (num))) + +void m_free_bluetooth(void *ptr_in) { + void **ptr = &((void**)ptr_in)[-2]; + if (ptr[1] != NULL) { + ((void**)ptr[1])[0] = ptr[0]; + } + if (ptr[0] != NULL) { + ((void**)ptr[0])[1] = ptr[1]; + } else { + MP_STATE_PORT(bluetooth_nimble_memory) = ptr[1]; + } + m_free(ptr); +} + +// Check if a nimble ptr is tracked. +// If it isn't, that means that it's from a previous soft-reset cycle. +STATIC bool is_valid_nimble_malloc(void *ptr) { + DEBUG_MALLOC_printf("NIMBLE is_valid_nimble_malloc(%p)\n", ptr); + void** search = MP_STATE_PORT(bluetooth_nimble_memory); + while (search) { + if (&search[2] == ptr) { + return true; + } + + search = (void**)search[1]; + } + return false; +} + +void *nimble_malloc(size_t size) { + DEBUG_MALLOC_printf("NIMBLE malloc(%u)\n", (uint)size); + void* ptr = m_malloc_bluetooth(size); + DEBUG_MALLOC_printf(" --> %p\n", ptr); + return ptr; +} + +// Only free if it's still a valid pointer. +void nimble_free(void *ptr) { + DEBUG_MALLOC_printf("NIMBLE free(%p)\n", ptr); + if (ptr && is_valid_nimble_malloc(ptr)) { + m_free_bluetooth(ptr); + } +} + +// Only realloc if it's still a valid pointer. Otherwise just malloc. +void *nimble_realloc(void *ptr, size_t size) { + // This is only used by ble_gatts.c to grow the queue of pending services to be registered. + DEBUG_MALLOC_printf("NIMBLE realloc(%p, %u)\n", ptr, (uint)size); + void *ptr2 = nimble_malloc(size); + if (ptr && is_valid_nimble_malloc(ptr)) { + // If it's a realloc and we still have the old data, then copy it. + // This will happen as we add services. + memcpy(ptr2, ptr, size); + m_free_bluetooth(ptr); + } + return ptr2; +} + +STATIC ble_uuid_t* create_nimble_uuid(const mp_obj_bluetooth_uuid_t *uuid) { + if (uuid->type == MP_BLUETOOTH_UUID_TYPE_16) { + ble_uuid16_t *result = m_new(ble_uuid16_t, 1); + result->u.type = BLE_UUID_TYPE_16; + result->value = uuid->uuid._16; + return (ble_uuid_t*)result; + } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_32) { + ble_uuid32_t *result = m_new(ble_uuid32_t, 1); + result->u.type = BLE_UUID_TYPE_32; + result->value = uuid->uuid._32; + return (ble_uuid_t*)result; + } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_128) { + ble_uuid128_t *result = m_new(ble_uuid128_t, 1); + result->u.type = BLE_UUID_TYPE_128; + memcpy(result->value, uuid->uuid._128, 16); + return (ble_uuid_t*)result; + } else { + return NULL; + } +} + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(const ble_uuid_any_t *uuid) { + mp_obj_bluetooth_uuid_t result; + switch (uuid->u.type) { + case BLE_UUID_TYPE_16: + result.type = MP_BLUETOOTH_UUID_TYPE_16; + result.uuid._16 = uuid->u16.value; + break; + case BLE_UUID_TYPE_32: + result.type = MP_BLUETOOTH_UUID_TYPE_32; + result.uuid._32 = uuid->u32.value; + break; + case BLE_UUID_TYPE_128: + result.type = MP_BLUETOOTH_UUID_TYPE_128; + memcpy(result.uuid._128, uuid->u128.value, 16); + break; + default: + assert(false); + } + return result; +} + +// modbluetooth (and the layers above it) work in BE addresses, Nimble works in LE. +STATIC void reverse_addr_byte_order(uint8_t *addr_out, const uint8_t *addr_in) { + for (int i = 0; i < 6; ++i) { + addr_out[i] = addr_in[5-i]; + } +} + +STATIC ble_addr_t create_nimble_addr(uint8_t addr_type, const uint8_t *addr) { + ble_addr_t addr_nimble; + addr_nimble.type = addr_type; + // Incoming addr is from modbluetooth (BE), so copy and convert to LE for Nimble. + reverse_addr_byte_order(addr_nimble.val, addr); + return addr_nimble; +} + +#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +STATIC mp_map_t *gatts_db = MP_OBJ_NULL; + +typedef struct { + uint8_t *data; + size_t data_alloc; + size_t data_len; +} gatts_db_entry_t; + +/******************************************************************************/ +// RUN LOOP + +enum { + BLE_STATE_OFF, + BLE_STATE_STARTING, + BLE_STATE_ACTIVE, +}; + +static volatile int ble_state = BLE_STATE_OFF; + +extern void nimble_uart_process(void); +extern void os_eventq_run_all(void); +extern void os_callout_process(void); + +// Hook for pendsv poller to run this periodically every 128ms +#define NIMBLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0) + +void nimble_poll(void) { + if (ble_state == BLE_STATE_OFF) { + return; + } + + nimble_uart_process(); + os_callout_process(); + os_eventq_run_all(); +} + +void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms) { + if (NIMBLE_TICK(ticks_ms)) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll); + } +} + +/******************************************************************************/ +// BINDINGS + +STATIC void reset_cb(int reason) { + (void)reason; +} + +STATIC void sync_cb(void) { + ble_hs_util_ensure_addr(0); // prefer public address + ble_svc_gap_device_name_set(MICROPY_PY_BLUETOOTH_DEFAULT_NAME); + + ble_state = BLE_STATE_ACTIVE; +} + +STATIC void create_gatts_db_entry(uint16_t handle) { + mp_map_elem_t *elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(handle), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + gatts_db_entry_t *entry = m_new(gatts_db_entry_t, 1); + entry->data = m_new(uint8_t, MP_BLUETOOTH_MAX_ATTR_SIZE); + entry->data_alloc = MP_BLUETOOTH_MAX_ATTR_SIZE; + entry->data_len = 0; + elem->value = MP_OBJ_FROM_PTR(entry); +} + +STATIC void gatts_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) { + switch (ctxt->op) { + case BLE_GATT_REGISTER_OP_SVC: + // Called when a service is successfully registered. + DEBUG_EVENT_printf("gatts_register_cb: svc uuid=%p handle=%d\n", &ctxt->svc.svc_def->uuid, ctxt->svc.handle); + break; + + case BLE_GATT_REGISTER_OP_CHR: + // Called when a characteristic is successfully registered. + DEBUG_EVENT_printf("gatts_register_cb: chr uuid=%p def_handle=%d val_handle=%d\n", &ctxt->chr.chr_def->uuid, ctxt->chr.def_handle, ctxt->chr.val_handle); + + // Note: We will get this event for the default GAP Service, meaning that we allocate storage for the + // "device name" and "appearance" characteristics, even though we never see the reads for them. + // TODO: Possibly check if the service UUID is 0x1801 and ignore? + + // Allocate the gatts_db storage for this characteristic. + // Although this function is a callback, it's called synchronously from ble_hs_sched_start/ble_gatts_start, so safe to allocate. + create_gatts_db_entry(ctxt->chr.val_handle); + break; + + case BLE_GATT_REGISTER_OP_DSC: + // Called when a descriptor is successfully registered. + // Note: This is event is not called for the CCCD. + DEBUG_EVENT_printf("gatts_register_cb: dsc uuid=%p handle=%d\n", &ctxt->dsc.dsc_def->uuid, ctxt->dsc.handle); + + // See above, safe to alloc. + create_gatts_db_entry(ctxt->dsc.handle); + + // Unlike characteristics, we have to manually provide a way to get the handle back to the register method. + *((uint16_t*)ctxt->dsc.dsc_def->arg) = ctxt->dsc.handle; + break; + + default: + DEBUG_EVENT_printf("gatts_register_cb: unknown op %d\n", ctxt->op); + break; + } +} + +STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) { + DEBUG_EVENT_printf("gap_event_cb: type=%d\n", event->type); + struct ble_gap_conn_desc desc; + uint8_t addr[6] = {0}; + + switch (event->type) { + case BLE_GAP_EVENT_CONNECT: + if (event->connect.status == 0) { + // Connection established. + ble_gap_conn_find(event->connect.conn_handle, &desc); + reverse_addr_byte_order(addr, desc.peer_id_addr.val); + mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_CONNECT, event->connect.conn_handle, desc.peer_id_addr.type, addr); + } else { + // Connection failed. + mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->connect.conn_handle, 0xff, addr); + } + break; + + case BLE_GAP_EVENT_DISCONNECT: + // Disconnect. + reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val); + mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr); + break; + } + + return 0; +} + +int mp_bluetooth_init(void) { + // Clean up if necessary. + mp_bluetooth_deinit(); + + MP_STATE_PORT(bluetooth_nimble_memory) = NULL; + + ble_hs_cfg.reset_cb = reset_cb; + ble_hs_cfg.sync_cb = sync_cb; + ble_hs_cfg.gatts_register_cb = gatts_register_cb; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + gatts_db = m_new_bluetooth(mp_map_t, 1); + + ble_hci_uart_init(); + nimble_port_init(); + + // By default, just register the default gap service. + ble_svc_gap_init(); + + ble_state = BLE_STATE_STARTING; + + ble_hs_start(); + + // Wait for sync callback + while (ble_state != BLE_STATE_ACTIVE) { + MICROPY_EVENT_POLL_HOOK + } + + return 0; +} + +// Called when the host stop procedure has completed. +STATIC void ble_hs_shutdown_stop_cb(int status, void *arg) { + ble_state = BLE_STATE_OFF; +} + +STATIC struct ble_hs_stop_listener ble_hs_shutdown_stop_listener; + +void mp_bluetooth_deinit(void) { + if (ble_state == BLE_STATE_OFF) { + return; + } + + mp_bluetooth_gap_advertise_stop(); + #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + mp_bluetooth_gap_scan_stop(); + #endif + + ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, + NULL); + + while (ble_state != BLE_STATE_OFF) { + MICROPY_EVENT_POLL_HOOK + } + + // TODO: This should be a port-specific hook. + #ifdef pyb_pin_BT_REG_ON + mp_hal_pin_low(pyb_pin_BT_REG_ON); + #endif +} + +bool mp_bluetooth_is_enabled(void) { + return ble_state == BLE_STATE_ACTIVE; +} + +void mp_bluetooth_get_device_addr(uint8_t *addr) { + mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr); +} + +int mp_bluetooth_gap_advertise_start(bool connectable, uint16_t interval_ms, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) { + int ret; + + mp_bluetooth_gap_advertise_stop(); + + if ((adv_data != NULL) && (adv_data_len > 0)) { + ret = ble_gap_adv_set_data(adv_data, adv_data_len); + if (ret != 0) { + return ble_hs_err_to_errno(ret); + } + } + + if ((sr_data != NULL) && (sr_data_len > 0)) { + ret = ble_gap_adv_rsp_set_data(sr_data, sr_data_len); + if (ret != 0) { + return ble_hs_err_to_errno(ret); + } + } + + // Convert from 1ms to 0.625ms units. + interval_ms = interval_ms * 8 / 5; + if (interval_ms < 0x20 || interval_ms > 0x4000) { + return MP_EINVAL; + } + + struct ble_gap_adv_params adv_params = { + .conn_mode = connectable ? BLE_GAP_CONN_MODE_UND : BLE_GAP_CONN_MODE_NON, + .disc_mode = BLE_GAP_DISC_MODE_GEN, + .itvl_min = interval_ms, + .itvl_max = interval_ms, + .channel_map = 7, // all 3 channels + }; + + ret = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); + if (ret != 0) { + return ble_hs_err_to_errno(ret); + } + + return 0; +} + +void mp_bluetooth_gap_advertise_stop(void) { + if (ble_gap_adv_active()) { + ble_gap_adv_stop(); + } +} + +static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + DEBUG_EVENT_printf("characteristic_access_cb: conn_handle=%u value_handle=%u op=%u\n", conn_handle, value_handle, ctxt->op); + mp_map_elem_t *elem; + gatts_db_entry_t *entry; + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + case BLE_GATT_ACCESS_OP_READ_DSC: + #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK + // Allow Python code to override (by using gatts_write), or deny (by returning false) the read. + if (!mp_bluetooth_gatts_on_read_request(conn_handle, value_handle)) { + return BLE_ATT_ERR_READ_NOT_PERMITTED; + } + #endif + + elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + if (!elem) { + return BLE_ATT_ERR_ATTR_NOT_FOUND; + } + entry = MP_OBJ_TO_PTR(elem->value); + + os_mbuf_append(ctxt->om, entry->data, entry->data_len); + + return 0; + case BLE_GATT_ACCESS_OP_WRITE_CHR: + case BLE_GATT_ACCESS_OP_WRITE_DSC: + elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + if (!elem) { + return BLE_ATT_ERR_ATTR_NOT_FOUND; + } + entry = MP_OBJ_TO_PTR(elem->value); + entry->data_len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(ctxt->om)); + os_mbuf_copydata(ctxt->om, 0, entry->data_len, entry->data); + + mp_bluetooth_gatts_on_write(conn_handle, value_handle); + + return 0; + } + return BLE_ATT_ERR_UNLIKELY; +} + +int mp_bluetooth_gatts_register_service_begin(bool reset) { + int ret = ble_gatts_reset(); + if (ret != 0) { + return ble_hs_err_to_errno(ret); + } + + // Reset the gatt characteristic value db. + mp_map_init(gatts_db, 0); + + // By default, just register the default gap service. + ble_svc_gap_init(); + + return 0; +} + +int mp_bluetooth_gatts_register_service_end() { + int ret = ble_gatts_start(); + if (ret != 0) { + return ble_hs_err_to_errno(ret); + } + + return 0; +} + +int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) { + // TODO: These allocs need to last until mp_bluetooth_gatts_register_service_end. + // Using m_new_bluetooth means they get leaked, but m_new would mean that they wouldn't be findable by GC. + size_t handle_index = 0; + size_t descriptor_index = 0; + + struct ble_gatt_chr_def *characteristics = m_new_bluetooth(struct ble_gatt_chr_def, num_characteristics + 1); + for (size_t i = 0; i < num_characteristics; ++i) { + characteristics[i].uuid = create_nimble_uuid(characteristic_uuids[i]); + characteristics[i].access_cb = characteristic_access_cb; + characteristics[i].arg = NULL; + characteristics[i].flags = characteristic_flags[i]; + characteristics[i].min_key_size = 0; + characteristics[i].val_handle = &handles[handle_index]; + ++handle_index; + + if (num_descriptors[i] == 0) { + characteristics[i].descriptors = NULL; + } else { + struct ble_gatt_dsc_def *descriptors = m_new_bluetooth(struct ble_gatt_dsc_def, num_descriptors[i] + 1); + + for (size_t j = 0; j < num_descriptors[i]; ++j) { + descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index]); + descriptors[j].access_cb = characteristic_access_cb; + descriptors[j].att_flags = descriptor_flags[i]; + descriptors[j].min_key_size = 0; + // Unlike characteristic, Nimble doesn't provide an automatic way to remember the handle, so use the arg. + descriptors[j].arg = &handles[handle_index]; + ++descriptor_index; + ++handle_index; + } + descriptors[num_descriptors[i]].uuid = NULL; // no more descriptors + + characteristics[i].descriptors = descriptors; + } + } + characteristics[num_characteristics].uuid = NULL; // no more characteristics + + struct ble_gatt_svc_def *service = m_new_bluetooth(struct ble_gatt_svc_def, 2); + service[0].type = BLE_GATT_SVC_TYPE_PRIMARY; + service[0].uuid = create_nimble_uuid(service_uuid); + service[0].includes = NULL; + service[0].characteristics = characteristics; + service[1].type = 0; // no more services + + // Note: advertising must be stopped for gatts registration to work + + int ret = ble_gatts_count_cfg(service); + if (ret != 0) { + return ble_hs_err_to_errno(ret); + } + + ret = ble_gatts_add_svcs(service); + if (ret != 0) { + return ble_hs_err_to_errno(ret); + } + + return 0; +} + +int mp_bluetooth_gap_disconnect(uint16_t conn_handle) { + return ble_hs_err_to_errno(ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM)); +} + +int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) { + mp_map_elem_t *elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + if (!elem) { + return MP_EINVAL; + } + gatts_db_entry_t *entry = MP_OBJ_TO_PTR(elem->value); + *value = entry->data; + *value_len = entry->data_len; + return 0; +} + +int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len) { + mp_map_elem_t *elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + if (!elem) { + return MP_EINVAL; + } + gatts_db_entry_t *entry = MP_OBJ_TO_PTR(elem->value); + if (value_len > entry->data_alloc) { + entry->data = m_new(uint8_t, value_len); + entry->data_alloc = value_len; + } + + memcpy(entry->data, value, value_len); + entry->data_len = value_len; + return 0; +} + +// TODO: Could use ble_gatts_chr_updated to send to all subscribed centrals. + +int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) { + // Confusingly, notify/notify_custom/indicate are "gattc" function (even though they're used by peripherals (i.e. gatt servers)). + // See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html + return ble_hs_err_to_errno(ble_gattc_notify(conn_handle, value_handle)); +} + +int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len) { + struct os_mbuf *om = ble_hs_mbuf_from_flat(value, *value_len); + if (om == NULL) { + return -1; + } + // TODO: check that notify_custom takes ownership of om, if not os_mbuf_free_chain(om). + return ble_hs_err_to_errno(ble_gattc_notify_custom(conn_handle, value_handle, om)); +} + +int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { + return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle)); +} + +#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { + DEBUG_EVENT_printf("gap_scan_cb: event=%d\n", event->type); + + if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) { + mp_bluetooth_gap_on_scan_complete(); + return 0; + } + + if (event->type != BLE_GAP_EVENT_DISC) { + return 0; + } + + DEBUG_EVENT_printf(" --> type %d\n", event->disc.event_type); + + + if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND) { + bool connectable = event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND; + uint8_t addr[6]; + reverse_addr_byte_order(addr, event->disc.addr.val); + mp_bluetooth_gap_on_scan_result(event->disc.addr.type, addr, connectable, event->disc.rssi, event->disc.data, event->disc.length_data); + } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { + // TODO + } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND) { + // TODO + } + + return 0; +} + +int mp_bluetooth_gap_scan_start(int32_t duration_ms) { + if (duration_ms == 0) { + duration_ms = BLE_HS_FOREVER; + } + STATIC const struct ble_gap_disc_params discover_params = { + .itvl = BLE_GAP_SCAN_SLOW_INTERVAL1, + .window = BLE_GAP_SCAN_SLOW_WINDOW1, + .filter_policy = BLE_HCI_CONN_FILT_NO_WL, + .limited = 0, + .passive = 0, + .filter_duplicates = 0, + }; + int err = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, duration_ms, &discover_params, gap_scan_cb, NULL); + return ble_hs_err_to_errno(err); +} + +int mp_bluetooth_gap_scan_stop(void) { + int err = ble_gap_disc_cancel(); + if (err == 0) { + mp_bluetooth_gap_on_scan_complete(); + return 0; + } + return ble_hs_err_to_errno(err); +} + +// Central role: GAP events for a connected peripheral. +STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { + DEBUG_EVENT_printf("peripheral_gap_event_cb: event=%d\n", event->type); + struct ble_gap_conn_desc desc; + uint8_t buf[MP_BLUETOOTH_MAX_ATTR_SIZE]; + size_t len; + uint8_t addr[6] = {0}; + + switch (event->type) { + case BLE_GAP_EVENT_CONNECT: + if (event->connect.status == 0) { + // Connection established. + ble_gap_conn_find(event->connect.conn_handle, &desc); + reverse_addr_byte_order(addr, desc.peer_id_addr.val); + mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT, event->connect.conn_handle, desc.peer_id_addr.type, addr); + } else { + // Connection failed. + mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT, event->connect.conn_handle, 0xff, addr); + } + break; + + case BLE_GAP_EVENT_DISCONNECT: + // Disconnect. + reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val); + mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr); + + break; + + case BLE_GAP_EVENT_NOTIFY_RX: + len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(event->notify_rx.om)); + os_mbuf_copydata(event->notify_rx.om, 0, len, buf); + if (event->notify_rx.indication == 0) { + mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_NOTIFY, event->notify_rx.conn_handle, event->notify_rx.attr_handle, buf, len); + } else { + mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_INDICATE, event->notify_rx.conn_handle, event->notify_rx.attr_handle, buf, len); + } + break; + + case BLE_GAP_EVENT_CONN_UPDATE: + // TODO + break; + + case BLE_GAP_EVENT_CONN_UPDATE_REQ: + // TODO + break; + + default: + break; + } + return 0; +} + +int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) { + if (ble_gap_disc_active()) { + mp_bluetooth_gap_scan_stop(); + } + + // TODO: This is the same as ble_gap_conn_params_dflt (i.e. passing NULL). + STATIC const struct ble_gap_conn_params params = { + .scan_itvl = 0x0010, + .scan_window = 0x0010, + .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN, + .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX, + .latency = BLE_GAP_INITIAL_CONN_LATENCY, + .supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT, + .min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN, + .max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN, + }; + + ble_addr_t addr_nimble = create_nimble_addr(addr_type, addr); + int err = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &addr_nimble, duration_ms, ¶ms, &peripheral_gap_event_cb, NULL); + return ble_hs_err_to_errno(err); +} + +STATIC int peripheral_discover_service_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) { + DEBUG_EVENT_printf("peripheral_discover_service_cb: conn_handle=%d status=%d start_handle=%d\n", conn_handle, error->status, service->start_handle); + // TODO: Find out what error->status == 14 means (probably "end of services"). + if (error->status == 0) { + mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(&service->uuid); + mp_bluetooth_gattc_on_primary_service_result(conn_handle, service->start_handle, service->end_handle, &service_uuid); + } + return 0; +} + +int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle) { + int err = ble_gattc_disc_all_svcs(conn_handle, &peripheral_discover_service_cb, NULL); + return ble_hs_err_to_errno(err); +} + +STATIC int ble_gatt_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) { + if (error->status == 0) { + mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid); + mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid); + } + return 0; +} + +int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) { + int err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gatt_characteristic_cb, NULL); + return ble_hs_err_to_errno(err); +} + +STATIC int ble_gatt_descriptor_cb(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t characteristic_val_handle, const struct ble_gatt_dsc *descriptor, void *arg) { + if (error->status == 0) { + mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(&descriptor->uuid); + mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor->handle, &descriptor_uuid); + } + return 0; +} + +int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) { + int err = ble_gattc_disc_all_dscs(conn_handle, start_handle, end_handle, &ble_gatt_descriptor_cb, NULL); + return ble_hs_err_to_errno(err); +} + +STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { + // TODO: Maybe send NULL if error->status non-zero. + if (error->status == 0) { + uint8_t buf[MP_BLUETOOTH_MAX_ATTR_SIZE]; + size_t len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(attr->om)); + os_mbuf_copydata(attr->om, 0, len, buf); + mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, buf, len); + } + return 0; +} + +// Initiate read of a value from the remote peripheral. +int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) { + int err = ble_gattc_read(conn_handle, value_handle, &ble_gatt_attr_read_cb, NULL); + return ble_hs_err_to_errno(err); +} + +STATIC int ble_gatt_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { + mp_bluetooth_gattc_on_write_status(conn_handle, attr->handle, error->status); + return 0; +} + +// Write the value to the remote peripheral. +int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len) { + int err = ble_gattc_write_flat(conn_handle, value_handle, value, *value_len, &ble_gatt_attr_write_cb, NULL); + return ble_hs_err_to_errno(err); +} + +#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE + +#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE From 5dc592d117b68455e8b1c1ef9230090c143358dc Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Sun, 1 Sep 2019 19:08:16 +1000 Subject: [PATCH 0496/1299] extmod/modbluetooth_nimble: Use random addr if public isn't available. --- extmod/modbluetooth_nimble.c | 43 ++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 3a6d1cba43d35..21d71e3c96979 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -277,7 +277,30 @@ STATIC void reset_cb(int reason) { } STATIC void sync_cb(void) { - ble_hs_util_ensure_addr(0); // prefer public address + int rc; + ble_addr_t addr; + + rc = ble_hs_util_ensure_addr(0); // prefer public address + if (rc != 0) { + // https://mynewt.apache.org/latest/tutorials/ble/eddystone.html#configure-the-nimble-stack-with-an-address + #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR + rc = ble_hs_id_gen_rnd(1, &addr); + assert(rc == 0); + rc = ble_hs_id_set_rnd(addr.val); + assert(rc == 0); + #else + uint8_t addr_be[6]; + mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr_be); + reverse_addr_byte_order(addr.val, addr_be); + // ble_hs_id_set_pub(addr.val); + rc = ble_hs_id_set_rnd(addr.val); + assert(rc == 0); + #endif + + rc = ble_hs_util_ensure_addr(0); // prefer public address + assert(rc == 0); + } + ble_svc_gap_device_name_set(MICROPY_PY_BLUETOOTH_DEFAULT_NAME); ble_state = BLE_STATE_ACTIVE; @@ -461,11 +484,23 @@ int mp_bluetooth_gap_advertise_start(bool connectable, uint16_t interval_ms, con }; ret = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); - if (ret != 0) { - return ble_hs_err_to_errno(ret); + if (ret == 0) { + return 0; + } + ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); + if (ret == 0) { + return 0; + } + ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_RANDOM_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); + if (ret == 0) { + return 0; + } + ret = ble_gap_adv_start(BLE_OWN_ADDR_RANDOM, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); + if (ret == 0) { + return 0; } - return 0; + return ble_hs_err_to_errno(ret); } void mp_bluetooth_gap_advertise_stop(void) { From eb1b6858a2c5454f84ab4bb0b854b96d234995c8 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 2 Sep 2019 15:40:31 +1000 Subject: [PATCH 0497/1299] extmod/modbluetooth: Allow MP_BLUETOOTH_MAX_ATTR_SIZE in board config. --- extmod/modbluetooth.h | 2 ++ extmod/modbluetooth_nimble.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 1b1318dec5380..9db3bed6cd586 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -48,7 +48,9 @@ #endif // Common constants. +#ifndef MP_BLUETOOTH_MAX_ATTR_SIZE #define MP_BLUETOOTH_MAX_ATTR_SIZE (20) +#endif // Advertisement packet lengths #define MP_BLUETOOTH_GAP_ADV_MAX_LEN (32) diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 21d71e3c96979..959360cee7545 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -301,6 +301,11 @@ STATIC void sync_cb(void) { assert(rc == 0); } + if (MP_BLUETOOTH_MAX_ATTR_SIZE > 20) { + rc = ble_att_set_preferred_mtu(MP_BLUETOOTH_MAX_ATTR_SIZE+3); + assert(rc == 0); + } + ble_svc_gap_device_name_set(MICROPY_PY_BLUETOOTH_DEFAULT_NAME); ble_state = BLE_STATE_ACTIVE; From 6f35f214d36ac9a58a069d163e3ab9ba05d650dd Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 30 Sep 2019 12:23:00 +1000 Subject: [PATCH 0498/1299] stm32/mpconfigport.h: Add modbluetooth module to stm32. --- ports/stm32/Makefile | 6 ++++++ ports/stm32/mpconfigport.h | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 0e3b4f8e3339b..40db2f7560359 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -379,6 +379,12 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ class/src/usbd_msc_scsi.c \ ) +ifeq ($(MICROPY_PY_BLUETOOTH),1) +CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 +CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 +CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK=1 +endif + ifeq ($(MICROPY_PY_NETWORK_CYW43),1) CFLAGS_MOD += -DMICROPY_PY_NETWORK_CYW43=1 SRC_C += sdio.c diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index b9c6cdedd7326..54e1c503c4f4b 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -211,6 +211,7 @@ extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_utime; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_network; +extern const struct _mp_obj_module_t mp_module_bluetooth; extern const struct _mp_obj_module_t mp_module_onewire; #if MICROPY_PY_STM @@ -245,6 +246,12 @@ extern const struct _mp_obj_module_t mp_module_onewire; #define NETWORK_BUILTIN_MODULE #endif +#if MICROPY_PY_BLUETOOTH +#define BLUETOOTH_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_bluetooth), MP_ROM_PTR(&mp_module_bluetooth) }, +#else +#define BLUETOOTH_BUILTIN_MODULE +#endif + #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_pyb), MP_ROM_PTR(&pyb_module) }, \ @@ -253,6 +260,7 @@ extern const struct _mp_obj_module_t mp_module_onewire; { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ SOCKET_BUILTIN_MODULE \ NETWORK_BUILTIN_MODULE \ + BLUETOOTH_BUILTIN_MODULE \ { MP_ROM_QSTR(MP_QSTR__onewire), MP_ROM_PTR(&mp_module_onewire) }, \ #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ From fafa9d35ddf90d35e14f32e736ac824631b09b38 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 27 Aug 2019 15:57:24 +1000 Subject: [PATCH 0499/1299] stm32/boards/PYBD: Enable BLE for Pyboard D. --- ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 4 ++++ ports/stm32/boards/PYBD_SF2/mpconfigboard.mk | 2 ++ ports/stm32/boards/PYBD_SF3/mpconfigboard.mk | 2 ++ ports/stm32/boards/PYBD_SF6/mpconfigboard.mk | 2 ++ 4 files changed, 10 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index 215b3f40165e0..8926ec081be78 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -177,6 +177,10 @@ extern struct _spi_bdev_t spi_bdev2; #define MICROPY_HW_USB_HS_IN_FS (1) #define MICROPY_HW_USB_MAIN_DEV (USB_PHY_HS_ID) +// Bluetooth config +#define MICROPY_HW_BLE_UART_ID (PYB_UART_6) +#define MICROPY_HW_BLE_UART_BAUDRATE (115200) + /******************************************************************************/ // Bootloader configuration diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk index 489d2f893a915..834a60b029ee8 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk @@ -10,6 +10,8 @@ TEXT0_SECTIONS = .isr_vector .text .data TEXT1_SECTIONS = .text_ext # MicroPython settings +MICROPY_PY_BLUETOOTH = 1 +MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 diff --git a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk index 368adcf39a65a..7bef5651dd57b 100644 --- a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk @@ -10,6 +10,8 @@ TEXT0_SECTIONS = .isr_vector .text .data TEXT1_SECTIONS = .text_ext # MicroPython settings +MICROPY_PY_BLUETOOTH = 1 +MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 diff --git a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk index 97c854ae77f74..f85d9c9973284 100644 --- a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk @@ -7,6 +7,8 @@ LD_FILES = boards/PYBD_SF6/f767.ld TEXT0_ADDR = 0x08008000 # MicroPython settings +MICROPY_PY_BLUETOOTH = 1 +MICROPY_BLUETOOTH_NIMBLE = 1 MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 From 1d7afcce49366c11f67561019a5adf5e60c450f5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 23 Sep 2019 23:32:31 +1000 Subject: [PATCH 0500/1299] py/bc: Remove comments referring to obsolete currently_in_except_block. It was made obsolete in 6f9e3ff719917616f163d3d671d6abe9472ba6ff --- py/bc.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/py/bc.h b/py/bc.h index e1b39c03d815e..dafd743760d4f 100644 --- a/py/bc.h +++ b/py/bc.h @@ -77,10 +77,10 @@ typedef struct _mp_bytecode_prelude_t { // Exception stack entry typedef struct _mp_exc_stack_t { const byte *handler; - // bit 0 is saved currently_in_except_block value + // bit 0 is currently unused // bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY mp_obj_t *val_sp; - // Saved exception, valid if currently_in_except_block bit is 1 + // Saved exception mp_obj_base_t *prev_exc; } mp_exc_stack_t; @@ -92,7 +92,6 @@ typedef struct _mp_code_state_t { mp_obj_fun_bc_t *fun_bc; const byte *ip; mp_obj_t *sp; - // bit 0 is saved currently_in_except_block value mp_exc_stack_t *exc_sp; mp_obj_dict_t *old_globals; #if MICROPY_STACKLESS From 4c5e1a036831a3ac36866e4daab3a50c772b4443 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 23 Sep 2019 23:37:01 +1000 Subject: [PATCH 0501/1299] py/bc: Change mp_code_state_t.exc_sp to exc_sp_idx. Change from a pointer to an index, to make space in mp_code_state_t. --- ports/unix/coverage.c | 2 +- py/bc.c | 2 +- py/bc.h | 9 ++++++++- py/objgenerator.c | 4 ++-- py/vm.c | 14 +++++++------- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index b6ebc9fb7eac6..6623cb4642bc2 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -385,7 +385,7 @@ STATIC mp_obj_t extra_coverage(void) { code_state->fun_bc = &fun_bc; code_state->ip = (const byte*)"\x00"; // just needed for an invalid opcode code_state->sp = &code_state->state[0]; - code_state->exc_sp = NULL; + code_state->exc_sp_idx = 0; code_state->old_globals = NULL; mp_vm_return_kind_t ret = mp_execute_bytecode(code_state, MP_OBJ_NULL); mp_printf(&mp_plat_print, "%d %d\n", ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError); diff --git a/py/bc.c b/py/bc.c index 6887dc43801e7..c32d5c415e240 100644 --- a/py/bc.c +++ b/py/bc.c @@ -133,7 +133,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw size_t n_def_pos_args = *code_state->ip++; code_state->sp = &code_state->state[0] - 1; - code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1; + code_state->exc_sp_idx = 0; // zero out the local stack to begin with memset(code_state->state, 0, n_state * sizeof(*code_state->state)); diff --git a/py/bc.h b/py/bc.h index dafd743760d4f..1d28dcc4f9360 100644 --- a/py/bc.h +++ b/py/bc.h @@ -60,6 +60,13 @@ // const0 : obj // constN : obj +// Sentinel value for mp_code_state_t.exc_sp_idx +#define MP_CODE_STATE_EXC_SP_IDX_SENTINEL ((uint16_t)-1) + +// To convert mp_code_state_t.exc_sp_idx to/from a pointer to mp_exc_stack_t +#define MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp) ((exc_sp) + 1 - (exc_stack)) +#define MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, exc_sp_idx) ((exc_stack) + (exc_sp_idx) - 1) + typedef struct _mp_bytecode_prelude_t { uint n_state; uint n_exc_stack; @@ -92,7 +99,7 @@ typedef struct _mp_code_state_t { mp_obj_fun_bc_t *fun_bc; const byte *ip; mp_obj_t *sp; - mp_exc_stack_t *exc_sp; + uint16_t exc_sp_idx; mp_obj_dict_t *old_globals; #if MICROPY_STACKLESS struct _mp_code_state_t *prev; diff --git a/py/objgenerator.c b/py/objgenerator.c index 62e6446166863..d32a74f3fb995 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -102,7 +102,7 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k mp_setup_code_state(&o->code_state, n_args, n_kw, args); // Indicate we are a native function, which doesn't use this variable - o->code_state.exc_sp = NULL; + o->code_state.exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_SENTINEL; // Prepare the generator instance for execution uintptr_t start_offset = ((uintptr_t*)self_fun->bytecode)[1]; @@ -172,7 +172,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ mp_vm_return_kind_t ret_kind; #if MICROPY_EMIT_NATIVE - if (self->code_state.exc_sp == NULL) { + if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) { // A native generator, with entry point 2 words into the "bytecode" pointer typedef uintptr_t (*mp_fun_native_gen_t)(void*, mp_obj_t); mp_fun_native_gen_t fun = MICROPY_MAKE_POINTER_CALLABLE((const void*)(self->code_state.fun_bc->bytecode + 2 * sizeof(uintptr_t))); diff --git a/py/vm.c b/py/vm.c index 16b1348b409d4..c0cd9ffbf8fcb 100644 --- a/py/vm.c +++ b/py/vm.c @@ -234,7 +234,7 @@ FRAME_SETUP(); } // variables that are visible to the exception handler (declared volatile) - mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack + mp_exc_stack_t *volatile exc_sp = MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, code_state->exc_sp_idx); // stack grows up, exc_sp points to top of stack #if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR // This needs to be volatile and outside the VM loop so it persists across handling @@ -953,7 +953,7 @@ unwind_jump:; if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; - code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, 0); + code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1); #if !MICROPY_ENABLE_PYSTACK if (new_state == NULL) { @@ -990,7 +990,7 @@ unwind_jump:; if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; - code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, 0); + code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); mp_call_args_t out_args; mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args); @@ -1034,7 +1034,7 @@ unwind_jump:; if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; - code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, 0); + code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); size_t n_args = unum & 0xff; size_t n_kw = (unum >> 8) & 0xff; @@ -1075,7 +1075,7 @@ unwind_jump:; if (mp_obj_get_type(*sp) == &mp_type_fun_bc) { code_state->ip = ip; code_state->sp = sp; - code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, 0); + code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); mp_call_args_t out_args; mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args); @@ -1197,7 +1197,7 @@ unwind_jump:; nlr_pop(); code_state->ip = ip; code_state->sp = sp; - code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, 0); + code_state->exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp); FRAME_LEAVE(); return MP_VM_RETURN_YIELD; @@ -1503,7 +1503,7 @@ unwind_jump:; fastn = &code_state->state[n_state - 1]; exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); // variables that are visible to the exception handler (declared volatile) - exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack + exc_sp = MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, code_state->exc_sp_idx); // stack grows up, exc_sp points to top of stack goto unwind_loop; #endif From 81d04a0200e0d4038c011e4946bfae5707ef9d9c Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 24 Sep 2019 15:57:08 +1000 Subject: [PATCH 0502/1299] py: Add n_state to mp_code_state_t struct. This value is used often enough that it is better to cache it instead of decode it each time. --- py/bc.h | 1 + py/emitnative.c | 3 +++ py/objfun.c | 7 ++++--- py/objgenerator.c | 2 ++ py/vm.c | 4 ++-- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/py/bc.h b/py/bc.h index 1d28dcc4f9360..69bce890288be 100644 --- a/py/bc.h +++ b/py/bc.h @@ -99,6 +99,7 @@ typedef struct _mp_code_state_t { mp_obj_fun_bc_t *fun_bc; const byte *ip; mp_obj_t *sp; + uint16_t n_state; uint16_t exc_sp_idx; mp_obj_dict_t *old_globals; #if MICROPY_STACKLESS diff --git a/py/emitnative.c b/py/emitnative.c index 760c7fb0c1280..f5a18c987a28e 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -521,6 +521,9 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // TODO this encoding may change size in the final pass, need to make it fixed emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, emit->prelude_offset, REG_ARG_1); + // Set code_state.n_state (only works on little endian targets due to n_state being uint16_t) + emit_native_mov_state_imm_via(emit, emit->code_state_start + offsetof(mp_code_state_t, n_state) / sizeof(uintptr_t), emit->n_state, REG_ARG_1); + // Put address of code_state into first arg ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, emit->code_state_start); diff --git a/py/objfun.c b/py/objfun.c index e0c6fb9271276..114367b4e0105 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -206,9 +206,10 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) { + n_exc_stack * sizeof(mp_exc_stack_t); \ } -#define INIT_CODESTATE(code_state, _fun_bc, n_args, n_kw, args) \ +#define INIT_CODESTATE(code_state, _fun_bc, _n_state, n_args, n_kw, args) \ code_state->fun_bc = _fun_bc; \ code_state->ip = 0; \ + code_state->n_state = _n_state; \ mp_setup_code_state(code_state, n_args, n_kw, args); \ code_state->old_globals = mp_globals_get(); @@ -235,7 +236,7 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args } #endif - INIT_CODESTATE(code_state, self, n_args, n_kw, args); + INIT_CODESTATE(code_state, self, n_state, n_args, n_kw, args); // execute the byte code with the correct globals context mp_globals_set(self->globals); @@ -280,7 +281,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } #endif - INIT_CODESTATE(code_state, self, n_args, n_kw, args); + INIT_CODESTATE(code_state, self, n_state, n_args, n_kw, args); // execute the byte code with the correct globals context mp_globals_set(self->globals); diff --git a/py/objgenerator.c b/py/objgenerator.c index d32a74f3fb995..39dcbefb9215c 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -62,6 +62,7 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons o->globals = self_fun->globals; o->code_state.fun_bc = self_fun; o->code_state.ip = 0; + o->code_state.n_state = n_state; mp_setup_code_state(&o->code_state, n_args, n_kw, args); return MP_OBJ_FROM_PTR(o); } @@ -99,6 +100,7 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k o->globals = self_fun->globals; o->code_state.fun_bc = self_fun; o->code_state.ip = (const byte*)prelude_offset; + o->code_state.n_state = n_state; mp_setup_code_state(&o->code_state, n_args, n_kw, args); // Indicate we are a native function, which doesn't use this variable diff --git a/py/vm.c b/py/vm.c index c0cd9ffbf8fcb..d59771b6e869b 100644 --- a/py/vm.c +++ b/py/vm.c @@ -228,7 +228,7 @@ FRAME_SETUP(); mp_obj_t * /*const*/ fastn; mp_exc_stack_t * /*const*/ exc_stack; { - size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode); + size_t n_state = code_state->n_state; fastn = &code_state->state[n_state - 1]; exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); } @@ -1499,7 +1499,7 @@ unwind_jump:; mp_nonlocal_free(code_state, sizeof(mp_code_state_t)); #endif code_state = new_code_state; - size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode); + size_t n_state = code_state->n_state; fastn = &code_state->state[n_state - 1]; exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); // variables that are visible to the exception handler (declared volatile) From b5ebfadbd615de42c43851f27a062bacd9147996 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Sep 2019 22:12:59 +1000 Subject: [PATCH 0503/1299] py: Compress first part of bytecode prelude. The start of the bytecode prelude contains 6 numbers telling the amount of stack needed for the Python values and exceptions, and the signature of the function. Prior to this patch these numbers were all encoded one after the other (2x variable unsigned integers, then 4x bytes), but using so many bytes is unnecessary. An entropy analysis of around 150,000 bytecode functions from the CPython standard library showed that the optimal Shannon coding would need about 7.1 bits on average to encode these 6 numbers, compared to the existing 48 bits. This patch attempts to get close to this optimal value by packing the 6 numbers into a single, varible-length unsigned integer via bit-wise interleaving. The interleaving scheme is chosen to minimise the average number of bytes needed, and at the same time keep the scheme simple enough so it can be implemented without too much overhead in code size or speed. The scheme requires about 10.5 bits on average to store the 6 numbers. As a result most functions which originally took 6 bytes to encode these 6 numbers now need only 1 byte (in 80% of cases). --- py/bc.c | 15 ++++--- py/bc.h | 74 +++++++++++++++++++++++++++++--- py/emitbc.c | 14 ++---- py/emitnative.c | 15 ++++--- py/objfun.c | 23 +++++----- py/objgenerator.c | 8 ++-- py/persistentcode.c | 41 ++++++++---------- py/profile.c | 13 +++--- py/runtime0.h | 4 +- py/showbc.c | 13 ++---- py/vm.c | 7 +-- tests/cmdline/cmd_verbose.py.exp | 2 +- tests/import/mpy_native.py | 4 +- tools/mpy-tool.py | 44 +++++++++++++------ 14 files changed, 171 insertions(+), 106 deletions(-) diff --git a/py/bc.c b/py/bc.c index c32d5c415e240..7544ffc5f2184 100644 --- a/py/bc.c +++ b/py/bc.c @@ -124,13 +124,14 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw code_state->frame = NULL; #endif - // get params - size_t n_state = mp_decode_uint(&code_state->ip); - code_state->ip = mp_decode_uint_skip(code_state->ip); // skip n_exc_stack - size_t scope_flags = *code_state->ip++; - size_t n_pos_args = *code_state->ip++; - size_t n_kwonly_args = *code_state->ip++; - size_t n_def_pos_args = *code_state->ip++; + // Get cached n_state (rather than decode it again) + size_t n_state = code_state->n_state; + + // Decode prelude + size_t n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; + MP_BC_PRELUDE_SIG_DECODE_INTO(code_state->ip, n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args); + (void)n_state_unused; + (void)n_exc_stack_unused; code_state->sp = &code_state->state[0] - 1; code_state->exc_sp_idx = 0; diff --git a/py/bc.h b/py/bc.h index 69bce890288be..1ae8c992586c2 100644 --- a/py/bc.h +++ b/py/bc.h @@ -32,12 +32,15 @@ // bytecode layout: // -// n_state : var uint -// n_exc_stack : var uint -// scope_flags : byte -// n_pos_args : byte number of arguments this function takes -// n_kwonly_args : byte number of keyword-only arguments this function takes -// n_def_pos_args : byte number of default positional arguments +// func signature : var uint +// contains six values interleaved bit-wise as: xSSSSEAA [xFSSKAED repeated] +// x = extension another byte follows +// S = n_state - 1 number of entries in Python value stack +// E = n_exc_stack number of entries in exception stack +// F = scope_flags four bits of flags, MP_SCOPE_FLAG_xxx +// A = n_pos_args number of arguments this function takes +// K = n_kwonly_args number of keyword-only arguments this function takes +// D = n_def_pos_args number of default positional arguments // // code_info_size : var uint | code_info_size counts bytes in this chunk // simple_name : var qstr | @@ -60,6 +63,65 @@ // const0 : obj // constN : obj +#define MP_BC_PRELUDE_SIG_ENCODE(S, E, scope, out_byte, out_env) \ +do { \ + /*// Get values to store in prelude */ \ + size_t F = scope->scope_flags & 0x0f; /* only need to store lower 4 flag bits */ \ + size_t A = scope->num_pos_args; \ + size_t K = scope->num_kwonly_args; \ + size_t D = scope->num_def_pos_args; \ + \ + /* Adjust S to shrink range, to compress better */ \ + S -= 1; \ + \ + /* Encode prelude */ \ + /* xSSSSEAA */ \ + uint8_t z = (S & 0xf) << 3 | (E & 1) << 2 | (A & 3); \ + S >>= 4; \ + E >>= 1; \ + A >>= 2; \ + while (S | E | F | A | K | D) { \ + out_byte(out_env, 0x80 | z); \ + /* xFSSKAED */ \ + z = (F & 1) << 6 | (S & 3) << 4 | (K & 1) << 3 \ + | (A & 1) << 2 | (E & 1) << 1 | (D & 1); \ + S >>= 2; \ + E >>= 1; \ + F >>= 1; \ + A >>= 1; \ + K >>= 1; \ + D >>= 1; \ + } \ + out_byte(out_env, z); \ +} while (0) + +#define MP_BC_PRELUDE_SIG_DECODE_INTO(ip, S, E, F, A, K, D) \ +do { \ + uint8_t z = *(ip)++; \ + /* xSSSSEAA */ \ + S = (z >> 3) & 0xf; \ + E = (z >> 2) & 0x1; \ + F = 0; \ + A = z & 0x3; \ + K = 0; \ + D = 0; \ + for (unsigned n = 0; z & 0x80; ++n) { \ + z = *(ip)++; \ + /* xFSSKAED */ \ + S |= (z & 0x30) << (2 * n); \ + E |= (z & 0x02) << n; \ + F |= ((z & 0x40) >> 6) << n; \ + A |= (z & 0x4) << n; \ + K |= ((z & 0x08) >> 3) << n; \ + D |= (z & 0x1) << n; \ + } \ + S += 1; \ +} while (0) + +#define MP_BC_PRELUDE_SIG_DECODE(ip) \ + size_t n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; \ + MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args) + // Sentinel value for mp_code_state_t.exc_sp_idx #define MP_CODE_STATE_EXC_SP_IDX_SENTINEL ((uint16_t)-1) diff --git a/py/emitbc.c b/py/emitbc.c index a8d57d27b0598..1aa219ca880c0 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -328,7 +328,7 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->bytecode_offset = 0; emit->code_info_offset = 0; - // Write local state size and exception stack size. + // Write local state size, exception stack size, scope flags and number of arguments { mp_uint_t n_state = scope->num_locals + scope->stack_size; if (n_state == 0) { @@ -341,16 +341,10 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { // An extra slot in the stack is needed to detect VM stack overflow n_state += 1; #endif - emit_write_code_info_uint(emit, n_state); - emit_write_code_info_uint(emit, scope->exc_stack_size); - } - // Write scope flags and number of arguments. - // TODO check that num args all fit in a byte - emit_write_code_info_byte(emit, emit->scope->scope_flags); - emit_write_code_info_byte(emit, emit->scope->num_pos_args); - emit_write_code_info_byte(emit, emit->scope->num_kwonly_args); - emit_write_code_info_byte(emit, emit->scope->num_def_pos_args); + size_t n_exc_stack = scope->exc_stack_size; + MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, scope, emit_write_code_info_byte, emit); + } // Write size of the rest of the code info. We don't know how big this // variable uint will be on the MP_PASS_CODE_SIZE pass so we reserve 2 bytes diff --git a/py/emitnative.c b/py/emitnative.c index f5a18c987a28e..d0e758f56c7a8 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -573,18 +573,19 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } +static inline void emit_native_write_code_info_byte(emit_t *emit, byte val) { + mp_asm_base_data(&emit->as->base, 1, val); +} + STATIC void emit_native_end_pass(emit_t *emit) { emit_native_global_exc_exit(emit); if (!emit->do_viper_types) { emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base); - mp_asm_base_data(&emit->as->base, 1, 0x80 | ((emit->n_state >> 7) & 0x7f)); - mp_asm_base_data(&emit->as->base, 1, emit->n_state & 0x7f); - mp_asm_base_data(&emit->as->base, 1, 0); // n_exc_stack - mp_asm_base_data(&emit->as->base, 1, emit->scope->scope_flags); - mp_asm_base_data(&emit->as->base, 1, emit->scope->num_pos_args); - mp_asm_base_data(&emit->as->base, 1, emit->scope->num_kwonly_args); - mp_asm_base_data(&emit->as->base, 1, emit->scope->num_def_pos_args); + + size_t n_state = emit->n_state; + size_t n_exc_stack = 0; // exc-stack not needed for native code + MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, emit->scope, emit_native_write_code_info_byte, emit); // write code info #if MICROPY_PERSISTENT_CODE diff --git a/py/objfun.c b/py/objfun.c index 114367b4e0105..053fe46b78568 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -161,12 +161,7 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { #endif const byte *bc = fun->bytecode; - bc = mp_decode_uint_skip(bc); // skip n_state - bc = mp_decode_uint_skip(bc); // skip n_exc_stack - bc++; // skip scope_params - bc++; // skip n_pos_args - bc++; // skip n_kwonly_args - bc++; // skip n_def_pos_args + MP_BC_PRELUDE_SIG_DECODE(bc); return mp_obj_code_get_name(bc); } @@ -197,10 +192,10 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) { #define DECODE_CODESTATE_SIZE(bytecode, n_state_out_var, state_size_out_var) \ { \ - /* bytecode prelude: state size and exception stack size */ \ - n_state_out_var = mp_decode_uint_value(bytecode); \ - size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(bytecode)); \ - \ + const uint8_t *ip = bytecode; \ + size_t n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_args; \ + MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state_out_var, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_args); \ + \ /* state size in bytes */ \ state_size_out_var = n_state_out_var * sizeof(mp_obj_t) \ + n_exc_stack * sizeof(mp_exc_stack_t); \ @@ -295,9 +290,11 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const assert(0); } } - const byte *bytecode_ptr = mp_decode_uint_skip(mp_decode_uint_skip(self->bytecode)); - size_t n_pos_args = bytecode_ptr[1]; - size_t n_kwonly_args = bytecode_ptr[2]; + const byte *bytecode_ptr = self->bytecode; + size_t n_state_unused, n_exc_stack_unused, scope_flags_unused; + size_t n_pos_args, n_kwonly_args, n_def_args_unused; + MP_BC_PRELUDE_SIG_DECODE_INTO(bytecode_ptr, n_state_unused, n_exc_stack_unused, + scope_flags_unused, n_pos_args, n_kwonly_args, n_def_args_unused); // We can't check the case when an exception is returned in state[0] // and there are no arguments, because in this case our detection slot may have // been overwritten by the returned exception (which is allowed). diff --git a/py/objgenerator.c b/py/objgenerator.c index 39dcbefb9215c..359dade88860c 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -51,8 +51,8 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in); // bytecode prelude: get state size and exception stack size - size_t n_state = mp_decode_uint_value(self_fun->bytecode); - size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self_fun->bytecode)); + const uint8_t *ip = self_fun->bytecode; + MP_BC_PRELUDE_SIG_DECODE(ip); // allocate the generator object, with room for local stack and exception stack mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, byte, @@ -88,7 +88,9 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k // Determine start of prelude, and extract n_state from it uintptr_t prelude_offset = ((uintptr_t*)self_fun->bytecode)[0]; - size_t n_state = mp_decode_uint_value(self_fun->bytecode + prelude_offset); + const uint8_t *ip = self_fun->bytecode + prelude_offset; + size_t n_state, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_args; + MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_args); size_t n_exc_stack = 0; // Allocate the generator object, with room for local stack and exception stack diff --git a/py/persistentcode.c b/py/persistentcode.c index 3b59746ba70ec..9776acb1e14d0 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -157,17 +157,16 @@ typedef struct _bytecode_prelude_t { uint code_info_size; } bytecode_prelude_t; -#if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_EMIT_MACHINE_CODE - // ip will point to start of opcodes // ip2 will point to simple_name, source_file qstrs STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_t *prelude) { - prelude->n_state = mp_decode_uint(ip); - prelude->n_exc_stack = mp_decode_uint(ip); - prelude->scope_flags = *(*ip)++; - prelude->n_pos_args = *(*ip)++; - prelude->n_kwonly_args = *(*ip)++; - prelude->n_def_pos_args = *(*ip)++; + MP_BC_PRELUDE_SIG_DECODE(*ip); + prelude->n_state = n_state; + prelude->n_exc_stack = n_exc_stack; + prelude->scope_flags = scope_flags; + prelude->n_pos_args = n_pos_args; + prelude->n_kwonly_args = n_kwonly_args; + prelude->n_def_pos_args = n_def_pos_args; *ip2 = *ip; prelude->code_info_size = mp_decode_uint(ip2); *ip += prelude->code_info_size; @@ -175,8 +174,6 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_ } } -#endif - #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE #if MICROPY_PERSISTENT_CODE_LOAD @@ -285,19 +282,19 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { } STATIC void load_prelude(mp_reader_t *reader, byte **ip, byte **ip2, bytecode_prelude_t *prelude) { - prelude->n_state = read_uint(reader, ip); - prelude->n_exc_stack = read_uint(reader, ip); - read_bytes(reader, *ip, 4); - prelude->scope_flags = *(*ip)++; - prelude->n_pos_args = *(*ip)++; - prelude->n_kwonly_args = *(*ip)++; - prelude->n_def_pos_args = *(*ip)++; - *ip2 = *ip; - prelude->code_info_size = read_uint(reader, ip2); - read_bytes(reader, *ip2, prelude->code_info_size - (*ip2 - *ip)); - *ip += prelude->code_info_size; - while ((*(*ip)++ = read_byte(reader)) != 255) { + // Read in the prelude + byte *ip_read = *ip; + read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint) + byte *ip_read_save = ip_read; + size_t code_info_size = read_uint(reader, &ip_read); // read in code_info_size + code_info_size -= ip_read - ip_read_save; // subtract bytes taken by code_info_size itself + read_bytes(reader, ip_read, code_info_size); // read remaining code info + ip_read += code_info_size; + while ((*ip_read++ = read_byte(reader)) != 255) { } + + // Entire prelude has been read into *ip, now decode and extract values from it + extract_prelude((const byte**)ip, (const byte**)ip2, prelude); } STATIC void load_bytecode(mp_reader_t *reader, qstr_window_t *qw, byte *ip, byte *ip_top) { diff --git a/py/profile.c b/py/profile.c index 8c4feaa11cac3..230bb7cc24304 100644 --- a/py/profile.c +++ b/py/profile.c @@ -40,12 +40,13 @@ STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) { void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) { const byte *ip = bytecode; - prelude->n_state = mp_decode_uint(&ip); - prelude->n_exc_stack = mp_decode_uint(&ip); - prelude->scope_flags = *ip++; - prelude->n_pos_args = *ip++; - prelude->n_kwonly_args = *ip++; - prelude->n_def_pos_args = *ip++; + MP_BC_PRELUDE_SIG_DECODE(ip); + prelude->n_state = n_state; + prelude->n_exc_stack = n_exc_stack; + prelude->scope_flags = scope_flags; + prelude->n_pos_args = n_pos_args; + prelude->n_kwonly_args = n_kwonly_args; + prelude->n_def_pos_args = n_def_pos_args; const byte *code_info = ip; size_t code_info_size = mp_decode_uint(&ip); diff --git a/py/runtime0.h b/py/runtime0.h index fd284d47b3b43..1df6d0d5837fd 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -28,9 +28,9 @@ // The first four must fit in 8 bits, see emitbc.c // The remaining must fit in 16 bits, see scope.h -#define MP_SCOPE_FLAG_VARARGS (0x01) +#define MP_SCOPE_FLAG_GENERATOR (0x01) #define MP_SCOPE_FLAG_VARKEYWORDS (0x02) -#define MP_SCOPE_FLAG_GENERATOR (0x04) +#define MP_SCOPE_FLAG_VARARGS (0x04) #define MP_SCOPE_FLAG_DEFKWARGS (0x08) #define MP_SCOPE_FLAG_REFGLOBALS (0x10) // used only if native emitter enabled #define MP_SCOPE_FLAG_HASCONSTS (0x20) // used only if native emitter enabled diff --git a/py/showbc.c b/py/showbc.c index 78b5b0141aac8..216f352664940 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -83,13 +83,8 @@ const mp_uint_t *mp_showbc_const_table; void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const mp_uint_t *const_table) { mp_showbc_code_start = ip; - // get bytecode parameters - mp_uint_t n_state = mp_decode_uint(&ip); - mp_uint_t n_exc_stack = mp_decode_uint(&ip); - /*mp_uint_t scope_flags =*/ ip++; - mp_uint_t n_pos_args = *ip++; - mp_uint_t n_kwonly_args = *ip++; - /*mp_uint_t n_def_pos_args =*/ ip++; + // Decode prelude + MP_BC_PRELUDE_SIG_DECODE(ip); const byte *code_info = ip; mp_uint_t code_info_size = mp_decode_uint(&code_info); @@ -123,8 +118,8 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m } printf("\n"); - printf("(N_STATE " UINT_FMT ")\n", n_state); - printf("(N_EXC_STACK " UINT_FMT ")\n", n_exc_stack); + printf("(N_STATE %u)\n", (unsigned)n_state); + printf("(N_EXC_STACK %u)\n", (unsigned)n_exc_stack); // for printing line number info const byte *bytecode_start = ip; diff --git a/py/vm.c b/py/vm.c index d59771b6e869b..82218fd9717db 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1440,12 +1440,7 @@ unwind_jump:; && *code_state->ip != MP_BC_END_FINALLY && *code_state->ip != MP_BC_RAISE_LAST) { const byte *ip = code_state->fun_bc->bytecode; - ip = mp_decode_uint_skip(ip); // skip n_state - ip = mp_decode_uint_skip(ip); // skip n_exc_stack - ip++; // skip scope_params - ip++; // skip n_pos_args - ip++; // skip n_kwonly_args - ip++; // skip n_def_pos_args + MP_BC_PRELUDE_SIG_DECODE(ip); size_t bc = code_state->ip - ip; size_t code_info_size = mp_decode_uint_value(ip); ip = mp_decode_uint_skip(ip); // skip code_info_size diff --git a/tests/cmdline/cmd_verbose.py.exp b/tests/cmdline/cmd_verbose.py.exp index 371c8c4b538dd..60b499c264557 100644 --- a/tests/cmdline/cmd_verbose.py.exp +++ b/tests/cmdline/cmd_verbose.py.exp @@ -1,6 +1,6 @@ File cmdline/cmd_verbose.py, code block '' (descriptor: \.\+, bytecode \.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): - 02 \.\+ + 08 \.\+ ######## \.\+63 arg names: diff --git a/tests/import/mpy_native.py b/tests/import/mpy_native.py index 25fceb9bb6651..03abab349e60e 100644 --- a/tests/import/mpy_native.py +++ b/tests/import/mpy_native.py @@ -56,8 +56,8 @@ def open(self, path, mode): '/mod1.mpy': ( b'M\x05\x0b\x1f\x20' # header - b'\x38' # n bytes, bytecode - b'\x01\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\xff' # prelude + b'\x24' # n bytes, bytecode + b'\x00\x05\x00\x00\x00\x00\xff' # prelude b'\x51' # LOAD_CONST_NONE b'\x63' # RETURN_VALUE diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 4f8e965d79850..8671a2395d7bb 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -152,13 +152,38 @@ def decode_uint(bytecode, ip): break return ip, unum +def read_prelude_sig(read_byte): + z = read_byte() + # xSSSSEAA + S = (z >> 3) & 0xf + E = (z >> 2) & 0x1 + F = 0 + A = z & 0x3 + K = 0 + D = 0 + n = 0 + while z & 0x80: + z = read_byte() + # xFSSKAED + S |= (z & 0x30) << (2 * n) + E |= (z & 0x02) << n + F |= ((z & 0x40) >> 6) << n + A |= (z & 0x4) << n + K |= ((z & 0x08) >> 3) << n + D |= (z & 0x1) << n + n += 1 + S += 1 + return S, E, F, A, K, D + def extract_prelude(bytecode, ip): - ip, n_state = decode_uint(bytecode, ip) - ip, n_exc_stack = decode_uint(bytecode, ip) - scope_flags = bytecode[ip]; ip += 1 - n_pos_args = bytecode[ip]; ip += 1 - n_kwonly_args = bytecode[ip]; ip += 1 - n_def_pos_args = bytecode[ip]; ip += 1 + def local_read_byte(): + b = bytecode[ip_ref[0]] + ip_ref[0] += 1 + return b + ip_ref = [ip] # to close over ip in Python 2 and 3 + n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(local_read_byte) + ip = ip_ref[0] + ip2, code_info_size = decode_uint(bytecode, ip) ip += code_info_size while bytecode[ip] != 0xff: @@ -557,12 +582,7 @@ def read_obj(f): assert 0 def read_prelude(f, bytecode): - n_state = read_uint(f, bytecode) - n_exc_stack = read_uint(f, bytecode) - scope_flags = read_byte(f, bytecode) - n_pos_args = read_byte(f, bytecode) - n_kwonly_args = read_byte(f, bytecode) - n_def_pos_args = read_byte(f, bytecode) + n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(lambda: read_byte(f, bytecode)) l1 = bytecode.idx code_info_size = read_uint(f, bytecode) l2 = bytecode.idx From c8c0fd4ca39fbdcf9ca5f2fc99ca4d6b81a28b65 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 25 Sep 2019 15:45:47 +1000 Subject: [PATCH 0504/1299] py: Rework and compress second part of bytecode prelude. This patch compresses the second part of the bytecode prelude which contains the source file name, function name, source-line-number mapping and cell closure information. This part of the prelude now begins with a single varible length unsigned integer which encodes 2 numbers, being the byte-size of the following 2 sections in the header: the "source info section" and the "closure section". After decoding this variable unsigned integer it's possible to skip over one or both of these sections very easily. This scheme saves about 2 bytes for most functions compared to the original format: one in the case that there are no closure cells, and one because padding was eliminated. --- py/bc.c | 14 +++++-- py/bc.h | 64 +++++++++++++++++++++++++----- py/emitbc.c | 43 ++++++++++---------- py/emitnative.c | 15 +++++-- py/objfun.c | 2 +- py/persistentcode.c | 16 +++----- py/profile.c | 17 +++----- py/showbc.c | 25 +++++------- py/vm.c | 11 +++-- tests/cmdline/cmd_parsetree.py.exp | 2 +- tests/cmdline/cmd_showbc.py.exp | 22 +++++----- tests/cmdline/cmd_verbose.py.exp | 2 +- tests/import/mpy_native.py | 4 +- tools/mpy-tool.py | 44 ++++++++++---------- 14 files changed, 162 insertions(+), 119 deletions(-) diff --git a/py/bc.c b/py/bc.c index 7544ffc5f2184..d671b64f921c5 100644 --- a/py/bc.c +++ b/py/bc.c @@ -269,19 +269,25 @@ continue2:; } } - // get the ip and skip argument names + // read the size part of the prelude const byte *ip = code_state->ip; + MP_BC_PRELUDE_SIZE_DECODE(ip); // jump over code info (source file and line-number mapping) - ip += mp_decode_uint_value(ip); + ip += n_info; // bytecode prelude: initialise closed over variables - size_t local_num; - while ((local_num = *ip++) != 255) { + for (; n_cell; --n_cell) { + size_t local_num = *ip++; code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]); } + #if !MICROPY_PERSISTENT_CODE + // so bytecode is aligned + ip = MP_ALIGN(ip, sizeof(mp_uint_t)); + #endif + // now that we skipped over the prelude, set the ip for the VM code_state->ip = ip; diff --git a/py/bc.h b/py/bc.h index 1ae8c992586c2..fd52571fdabef 100644 --- a/py/bc.h +++ b/py/bc.h @@ -42,17 +42,25 @@ // K = n_kwonly_args number of keyword-only arguments this function takes // D = n_def_pos_args number of default positional arguments // -// code_info_size : var uint | code_info_size counts bytes in this chunk -// simple_name : var qstr | -// source_file : var qstr | -// | -// | only needed if bytecode contains pointers +// prelude size : var uint +// contains two values interleaved bit-wise as: xIIIIIIC repeated +// x = extension another byte follows +// I = n_info number of bytes in source info section +// C = n_cells number of bytes/cells in closure section +// +// source info section: +// simple_name : var qstr +// source_file : var qstr +// +// +// closure section: +// local_num0 : byte +// ... : byte +// local_numN : byte N = n_cells-1 +// +// only needed if bytecode contains pointers // -// local_num0 : byte | -// ... : byte | -// local_numN : byte | N = num_cells -// 255 : byte | end of list sentinel -// | +// // // // constant table layout: @@ -122,6 +130,41 @@ do { \ size_t n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; \ MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args) +#define MP_BC_PRELUDE_SIZE_ENCODE(I, C, out_byte, out_env) \ +do { \ + /* Encode bit-wise as: xIIIIIIC */ \ + uint8_t z = 0; \ + do { \ + z = (I & 0x3f) << 1 | (C & 1); \ + C >>= 1; \ + I >>= 6; \ + if (C | I) { \ + z |= 0x80; \ + } \ + out_byte(out_env, z); \ + } while (C | I); \ +} while (0) + +#define MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, I, C) \ +do { \ + uint8_t z; \ + C = 0; \ + I = 0; \ + for (unsigned n = 0;; ++n) { \ + z = *(ip)++; \ + /* xIIIIIIC */ \ + C |= (z & 1) << n; \ + I |= ((z & 0x7e) >> 1) << (6 * n); \ + if (!(z & 0x80)) { \ + break; \ + } \ + } \ +} while (0) + +#define MP_BC_PRELUDE_SIZE_DECODE(ip) \ + size_t n_info, n_cell; \ + MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, n_info, n_cell) + // Sentinel value for mp_code_state_t.exc_sp_idx #define MP_CODE_STATE_EXC_SP_IDX_SENTINEL ((uint16_t)-1) @@ -139,7 +182,6 @@ typedef struct _mp_bytecode_prelude_t { qstr qstr_block_name; qstr qstr_source_file; const byte *line_info; - const byte *locals; const byte *opcodes; } mp_bytecode_prelude_t; diff --git a/py/emitbc.c b/py/emitbc.c index 1aa219ca880c0..34f6362ff000b 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -64,6 +64,9 @@ struct _emit_t { size_t bytecode_size; byte *code_base; // stores both byte code and code info + size_t n_info; + size_t n_cell; + #if MICROPY_PERSISTENT_CODE uint16_t ct_cur_obj; uint16_t ct_num_obj; @@ -123,10 +126,6 @@ STATIC void emit_write_code_info_byte(emit_t* emit, byte val) { *emit_get_cur_to_write_code_info(emit, 1) = val; } -STATIC void emit_write_code_info_uint(emit_t* emit, mp_uint_t val) { - emit_write_uint(emit, emit_get_cur_to_write_code_info, val); -} - STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) { #if MICROPY_PERSISTENT_CODE assert((qst >> 16) == 0); @@ -346,29 +345,17 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, scope, emit_write_code_info_byte, emit); } - // Write size of the rest of the code info. We don't know how big this - // variable uint will be on the MP_PASS_CODE_SIZE pass so we reserve 2 bytes - // for it and hope that is enough! TODO assert this or something. - if (pass == MP_PASS_EMIT) { - emit_write_code_info_uint(emit, emit->code_info_size - emit->code_info_offset); - } else { - emit_get_cur_to_write_code_info(emit, 2); + // Write number of cells and size of the source code info + if (pass >= MP_PASS_CODE_SIZE) { + MP_BC_PRELUDE_SIZE_ENCODE(emit->n_info, emit->n_cell, emit_write_code_info_byte, emit); } + emit->n_info = emit->code_info_offset; + // Write the name and source file of this function. emit_write_code_info_qstr(emit, scope->simple_name); emit_write_code_info_qstr(emit, scope->source_file); - // bytecode prelude: initialise closed over variables - for (int i = 0; i < scope->id_info_len; i++) { - id_info_t *id = &scope->id_info[i]; - if (id->kind == ID_INFO_KIND_CELL) { - assert(id->local_num < 255); - emit_write_bytecode_raw_byte(emit, id->local_num); // write the local which should be converted to a cell - } - } - emit_write_bytecode_raw_byte(emit, 255); // end of list sentinel - #if MICROPY_PERSISTENT_CODE emit->ct_cur_obj = 0; emit->ct_cur_raw_code = 0; @@ -414,6 +401,20 @@ void mp_emit_bc_end_pass(emit_t *emit) { emit_write_code_info_byte(emit, 0); // end of line number info + // Calculate size of source code info section + emit->n_info = emit->code_info_offset - emit->n_info; + + // Emit closure section of prelude + emit->n_cell = 0; + for (size_t i = 0; i < emit->scope->id_info_len; ++i) { + id_info_t *id = &emit->scope->id_info[i]; + if (id->kind == ID_INFO_KIND_CELL) { + assert(id->local_num <= 255); + emit_write_code_info_byte(emit, id->local_num); // write the local which should be converted to a cell + ++emit->n_cell; + } + } + #if MICROPY_PERSISTENT_CODE assert(emit->pass <= MP_PASS_STACK_SIZE || (emit->ct_num_obj == emit->ct_cur_obj)); emit->ct_num_obj = emit->ct_cur_obj; diff --git a/py/emitnative.c b/py/emitnative.c index d0e758f56c7a8..2c976606c717d 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -208,6 +208,7 @@ struct _emit_t { uint16_t code_state_start; uint16_t stack_start; int stack_size; + uint16_t n_cell; uint16_t const_table_cur_obj; uint16_t const_table_num_obj; @@ -587,9 +588,14 @@ STATIC void emit_native_end_pass(emit_t *emit) { size_t n_exc_stack = 0; // exc-stack not needed for native code MP_BC_PRELUDE_SIG_ENCODE(n_state, n_exc_stack, emit->scope, emit_native_write_code_info_byte, emit); - // write code info #if MICROPY_PERSISTENT_CODE - mp_asm_base_data(&emit->as->base, 1, 5); + size_t n_info = 4; + #else + size_t n_info = 1; + #endif + MP_BC_PRELUDE_SIZE_ENCODE(n_info, emit->n_cell, emit_native_write_code_info_byte, emit); + + #if MICROPY_PERSISTENT_CODE mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name); mp_asm_base_data(&emit->as->base, 1, emit->scope->simple_name >> 8); mp_asm_base_data(&emit->as->base, 1, emit->scope->source_file); @@ -599,14 +605,15 @@ STATIC void emit_native_end_pass(emit_t *emit) { #endif // bytecode prelude: initialise closed over variables + size_t cell_start = mp_asm_base_get_code_pos(&emit->as->base); for (int i = 0; i < emit->scope->id_info_len; i++) { id_info_t *id = &emit->scope->id_info[i]; if (id->kind == ID_INFO_KIND_CELL) { - assert(id->local_num < 255); + assert(id->local_num <= 255); mp_asm_base_data(&emit->as->base, 1, id->local_num); // write the local which should be converted to a cell } } - mp_asm_base_data(&emit->as->base, 1, 255); // end of list sentinel + emit->n_cell = mp_asm_base_get_code_pos(&emit->as->base) - cell_start; } ASM_END_PASS(emit->as); diff --git a/py/objfun.c b/py/objfun.c index 053fe46b78568..7051f3476d456 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -139,7 +139,7 @@ const mp_obj_type_t mp_type_fun_builtin_var = { /* byte code functions */ qstr mp_obj_code_get_name(const byte *code_info) { - code_info = mp_decode_uint_skip(code_info); // skip code_info_size entry + MP_BC_PRELUDE_SIZE_DECODE(code_info); #if MICROPY_PERSISTENT_CODE return code_info[0] | (code_info[1] << 8); #else diff --git a/py/persistentcode.c b/py/persistentcode.c index 9776acb1e14d0..2109d937989c9 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -167,11 +167,10 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_ prelude->n_pos_args = n_pos_args; prelude->n_kwonly_args = n_kwonly_args; prelude->n_def_pos_args = n_def_pos_args; + MP_BC_PRELUDE_SIZE_DECODE(*ip); *ip2 = *ip; - prelude->code_info_size = mp_decode_uint(ip2); - *ip += prelude->code_info_size; - while (*(*ip)++ != 255) { - } + *ip += n_info; + *ip += n_cell; } #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE @@ -286,12 +285,9 @@ STATIC void load_prelude(mp_reader_t *reader, byte **ip, byte **ip2, bytecode_pr byte *ip_read = *ip; read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint) byte *ip_read_save = ip_read; - size_t code_info_size = read_uint(reader, &ip_read); // read in code_info_size - code_info_size -= ip_read - ip_read_save; // subtract bytes taken by code_info_size itself - read_bytes(reader, ip_read, code_info_size); // read remaining code info - ip_read += code_info_size; - while ((*ip_read++ = read_byte(reader)) != 255) { - } + read_uint(reader, &ip_read); // read in n_info/n_cell (is effectively a var-uint) + MP_BC_PRELUDE_SIZE_DECODE(ip_read_save); + read_bytes(reader, ip_read, n_info + n_cell); // read remaining code info // Entire prelude has been read into *ip, now decode and extract values from it extract_prelude((const byte**)ip, (const byte**)ip2, prelude); diff --git a/py/profile.c b/py/profile.c index 230bb7cc24304..f16d4d701ee1f 100644 --- a/py/profile.c +++ b/py/profile.c @@ -34,7 +34,7 @@ STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) { const mp_bytecode_prelude_t *prelude = &rc->prelude; - return mp_bytecode_get_source_line(prelude->line_info, bc + prelude->opcodes - prelude->locals); + return mp_bytecode_get_source_line(prelude->line_info, bc); } void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude) { @@ -48,22 +48,15 @@ void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelud prelude->n_kwonly_args = n_kwonly_args; prelude->n_def_pos_args = n_def_pos_args; - const byte *code_info = ip; - size_t code_info_size = mp_decode_uint(&ip); + MP_BC_PRELUDE_SIZE_DECODE(ip); + + prelude->line_info = ip + 4; + prelude->opcodes = ip + n_info + n_cell; qstr block_name = ip[0] | (ip[1] << 8); qstr source_file = ip[2] | (ip[3] << 8); - ip += 4; prelude->qstr_block_name = block_name; prelude->qstr_source_file = source_file; - - prelude->line_info = ip; - prelude->locals = code_info + code_info_size; - - ip = prelude->locals; - while (*ip++ != 255) { - } - prelude->opcodes = ip; } /******************************************************************************/ diff --git a/py/showbc.c b/py/showbc.c index 216f352664940..d154511dce8dc 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -85,10 +85,8 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m // Decode prelude MP_BC_PRELUDE_SIG_DECODE(ip); - + MP_BC_PRELUDE_SIZE_DECODE(ip); const byte *code_info = ip; - mp_uint_t code_info_size = mp_decode_uint(&code_info); - ip += code_info_size; #if MICROPY_PERSISTENT_CODE qstr block_name = code_info[0] | (code_info[1] << 8); @@ -102,7 +100,9 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m qstr_str(source_file), qstr_str(block_name), descr, mp_showbc_code_start, len); // raw bytecode dump - printf("Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n", code_info_size, len - code_info_size); + size_t prelude_size = ip - mp_showbc_code_start + n_info + n_cell; + printf("Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n", + prelude_size, len - prelude_size); for (mp_uint_t i = 0; i < len; i++) { if (i > 0 && i % 16 == 0) { printf("\n"); @@ -121,21 +121,18 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m printf("(N_STATE %u)\n", (unsigned)n_state); printf("(N_EXC_STACK %u)\n", (unsigned)n_exc_stack); - // for printing line number info - const byte *bytecode_start = ip; + // skip over code_info + ip += n_info; // bytecode prelude: initialise closed over variables - { - uint local_num; - while ((local_num = *ip++) != 255) { - printf("(INIT_CELL %u)\n", local_num); - } - len -= ip - mp_showbc_code_start; + for (size_t i = 0; i < n_cell; ++i) { + uint local_num = *ip++; + printf("(INIT_CELL %u)\n", local_num); } // print out line number info { - mp_int_t bc = bytecode_start - ip; + mp_int_t bc = 0; mp_uint_t source_line = 1; printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); for (const byte* ci = code_info; *ci;) { @@ -153,7 +150,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len, const m printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); } } - mp_bytecode_print2(ip, len - 0, const_table); + mp_bytecode_print2(ip, len - prelude_size, const_table); } const byte *mp_bytecode_print_str(const byte *ip) { diff --git a/py/vm.c b/py/vm.c index 82218fd9717db..7487ff61b4fff 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1441,10 +1441,13 @@ unwind_jump:; && *code_state->ip != MP_BC_RAISE_LAST) { const byte *ip = code_state->fun_bc->bytecode; MP_BC_PRELUDE_SIG_DECODE(ip); - size_t bc = code_state->ip - ip; - size_t code_info_size = mp_decode_uint_value(ip); - ip = mp_decode_uint_skip(ip); // skip code_info_size - bc -= code_info_size; + MP_BC_PRELUDE_SIZE_DECODE(ip); + const byte *bytecode_start = ip + n_info + n_cell; + #if !MICROPY_PERSISTENT_CODE + // so bytecode is aligned + bytecode_start = MP_ALIGN(bytecode_start, sizeof(mp_uint_t)); + #endif + size_t bc = code_state->ip - bytecode_start; #if MICROPY_PERSISTENT_CODE qstr block_name = ip[0] | (ip[1] << 8); qstr source_file = ip[2] | (ip[3] << 8); diff --git a/tests/cmdline/cmd_parsetree.py.exp b/tests/cmdline/cmd_parsetree.py.exp index 58d419dc46b29..18986318a02b4 100644 --- a/tests/cmdline/cmd_parsetree.py.exp +++ b/tests/cmdline/cmd_parsetree.py.exp @@ -36,7 +36,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: (N_STATE 5) (N_EXC_STACK 0) - bc=-1 line=1 + bc=0 line=1 bc=0 line=4 bc=9 line=5 bc=12 line=6 diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 839034a69f4ab..b0a9016c517cb 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -5,7 +5,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: (N_STATE 3) (N_EXC_STACK 0) - bc=-1 line=1 + bc=0 line=1 ######## bc=\\d\+ line=155 00 MAKE_FUNCTION \.\+ @@ -38,7 +38,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): (INIT_CELL 14) (INIT_CELL 15) (INIT_CELL 16) - bc=-4 line=1 + bc=0 line=1 ######## bc=\\d\+ line=126 00 LOAD_CONST_NONE @@ -318,7 +318,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \.\+rg names: (N_STATE 22) (N_EXC_STACK 0) - bc=-1 line=1 + bc=0 line=1 ######## bc=\\d\+ line=132 00 LOAD_CONST_SMALL_INT 1 @@ -392,7 +392,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: (N_STATE 2) (N_EXC_STACK 0) - bc=-1 line=1 + bc=0 line=1 bc=0 line=143 bc=3 line=144 bc=6 line=145 @@ -416,7 +416,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: (N_STATE 1) (N_EXC_STACK 0) - bc=-1 line=1 + bc=0 line=1 ######## bc=13 line=149 00 LOAD_NAME __name__ (cache=0) @@ -432,7 +432,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: self (N_STATE 4) (N_EXC_STACK 0) - bc=-1 line=1 + bc=0 line=1 bc=0 line=156 00 LOAD_GLOBAL super (cache=0) \\d\+ LOAD_GLOBAL __class__ (cache=0) @@ -449,7 +449,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: * * * (N_STATE 9) (N_EXC_STACK 0) - bc=-\\d\+ line=1 + bc=0 line=1 bc=0 line=59 ######## 00 LOAD_NULL @@ -473,7 +473,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: * * * (N_STATE 10) (N_EXC_STACK 0) - bc=-\\d\+ line=1 + bc=0 line=1 bc=0 line=60 ######## 00 BUILD_LIST 0 @@ -494,7 +494,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: * * * (N_STATE 11) (N_EXC_STACK 0) - bc=-\\d\+ line=1 + bc=0 line=1 ######## 00 BUILD_MAP 0 02 LOAD_FAST 2 @@ -515,7 +515,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: * (N_STATE 4) (N_EXC_STACK 0) - bc=-\\d\+ line=1 + bc=0 line=1 ######## bc=\\d\+ line=113 00 LOAD_DEREF 0 @@ -534,7 +534,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: * b (N_STATE 4) (N_EXC_STACK 0) - bc=-\\d\+ line=1 + bc=0 line=1 ######## bc=\\d\+ line=139 00 LOAD_FAST 1 diff --git a/tests/cmdline/cmd_verbose.py.exp b/tests/cmdline/cmd_verbose.py.exp index 60b499c264557..a2fdf1f00deb3 100644 --- a/tests/cmdline/cmd_verbose.py.exp +++ b/tests/cmdline/cmd_verbose.py.exp @@ -6,7 +6,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): arg names: (N_STATE 2) (N_EXC_STACK 0) - bc=-1 line=1 + bc=0 line=1 bc=0 line=3 00 LOAD_NAME print (cache=0) 04 LOAD_CONST_SMALL_INT 1 diff --git a/tests/import/mpy_native.py b/tests/import/mpy_native.py index 03abab349e60e..749320dbbe606 100644 --- a/tests/import/mpy_native.py +++ b/tests/import/mpy_native.py @@ -56,8 +56,8 @@ def open(self, path, mode): '/mod1.mpy': ( b'M\x05\x0b\x1f\x20' # header - b'\x24' # n bytes, bytecode - b'\x00\x05\x00\x00\x00\x00\xff' # prelude + b'\x20' # n bytes, bytecode + b'\x00\x08\x00\x00\x00\x00' # prelude b'\x51' # LOAD_CONST_NONE b'\x63' # RETURN_VALUE diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 8671a2395d7bb..8c0f5db18a931 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -142,16 +142,6 @@ def mp_opcode_format(bytecode, ip, count_var_uint): ip += extra_byte return f, ip - ip_start -def decode_uint(bytecode, ip): - unum = 0 - while True: - val = bytecode[ip] - ip += 1 - unum = (unum << 7) | (val & 0x7f) - if not (val & 0x80): - break - return ip, unum - def read_prelude_sig(read_byte): z = read_byte() # xSSSSEAA @@ -175,6 +165,20 @@ def read_prelude_sig(read_byte): S += 1 return S, E, F, A, K, D +def read_prelude_size(read_byte): + I = 0 + C = 0 + n = 0 + while True: + z = read_byte() + # xIIIIIIC + I |= ((z & 0x7e) >> 1) << (6 * n) + C |= (z & 1) << n + if not (z & 0x80): + break + n += 1 + return I, C + def extract_prelude(bytecode, ip): def local_read_byte(): b = bytecode[ip_ref[0]] @@ -182,16 +186,14 @@ def local_read_byte(): return b ip_ref = [ip] # to close over ip in Python 2 and 3 n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(local_read_byte) + n_info, n_cell = read_prelude_size(local_read_byte) ip = ip_ref[0] - ip2, code_info_size = decode_uint(bytecode, ip) - ip += code_info_size - while bytecode[ip] != 0xff: - ip += 1 - ip += 1 + ip2 = ip + ip = ip2 + n_info + n_cell # ip now points to first opcode # ip2 points to simple_name qstr - return ip, ip2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args, code_info_size) + return ip, ip2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args) class MPFunTable: pass @@ -359,7 +361,6 @@ def freeze_module(self, qstr_links=(), type_sig=0): print(' .qstr_block_name = %s,' % self.simple_name.qstr_id) print(' .qstr_source_file = %s,' % self.source_file.qstr_id) print(' .line_info = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO - print(' .locals = fun_data_%s + %u,' % (self.escaped_name, 0)) # TODO print(' .opcodes = fun_data_%s + %u,' % (self.escaped_name, self.ip)) print(' },') print(' .line_of_definition = %u,' % 0) # TODO @@ -583,14 +584,11 @@ def read_obj(f): def read_prelude(f, bytecode): n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(lambda: read_byte(f, bytecode)) - l1 = bytecode.idx - code_info_size = read_uint(f, bytecode) + n_info, n_cell = read_prelude_size(lambda: read_byte(f, bytecode)) l2 = bytecode.idx - for _ in range(code_info_size - (l2 - l1)): + for _ in range(n_info + n_cell): read_byte(f, bytecode) - while read_byte(f, bytecode) != 255: - pass - return l2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args, code_info_size) + return l2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args) def read_qstr_and_pack(f, bytecode, qstr_win): qst = read_qstr(f, qstr_win) From fd9b7efe3957f2f0b24d9cec2fe38ddaccf0539d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 25 Sep 2019 16:19:29 +1000 Subject: [PATCH 0505/1299] minimal/frozentest.mpy: Update due to change in bytecode. --- ports/minimal/frozentest.mpy | Bin 207 -> 200 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/ports/minimal/frozentest.mpy b/ports/minimal/frozentest.mpy index f1cebe3fed8875321215ad4e8ea485fc381112fa..178b811ba0924a78ea825c22983ebbd9c597c2ff 100644 GIT binary patch delta 28 jcmX@lc!E*Hmz7Cgp(#W_jGZBnQBy-hLtBGkqVyI3SZ@XD delta 35 ocmX@Xc%D((mz7Cgp{anG0R(v283Gx#G&D4{H5eHFPZZe#0CwjF@Bjb+ From 1d0423419b6da1f865ad73e1a95f26e724770ab7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 26 Sep 2019 11:48:07 +1000 Subject: [PATCH 0506/1299] py/bc: Don't include mp_decode_uint funcs when not needed. These are now only needed when persistent code is disabled. --- py/bc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/py/bc.c b/py/bc.c index d671b64f921c5..7dd4b2246a69a 100644 --- a/py/bc.c +++ b/py/bc.c @@ -40,6 +40,8 @@ #define DEBUG_printf(...) (void)0 #endif +#if !MICROPY_PERSISTENT_CODE + mp_uint_t mp_decode_uint(const byte **ptr) { mp_uint_t unum = 0; byte val; @@ -70,6 +72,8 @@ const byte *mp_decode_uint_skip(const byte *ptr) { return ptr; } +#endif + STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE // generic message, used also for other argument issues From 4102320e908dfa6e2fc320d73f118670ad5b1501 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 26 Sep 2019 11:48:39 +1000 Subject: [PATCH 0507/1299] tests/basics: Add test for getting name of func with closed over locals. Tests correct decoding of the prelude to get the function name. --- tests/basics/fun_name.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/basics/fun_name.py b/tests/basics/fun_name.py index 53ca935616ce3..bb1f14992f70f 100644 --- a/tests/basics/fun_name.py +++ b/tests/basics/fun_name.py @@ -22,3 +22,11 @@ def Fun(self): str((1).to_bytes.__name__) except AttributeError: pass + +# name of a function that has closed over variables +def outer(): + x = 1 + def inner(): + return x + return inner +print(outer.__name__) From d2e730b727fe5522e8b70b3af48bc4504545eb3b Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Sun, 23 Dec 2018 16:22:00 +0100 Subject: [PATCH 0508/1299] nrf/i2c: Add support for TWIM (EasyDMA). --- ports/nrf/modules/machine/i2c.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/ports/nrf/modules/machine/i2c.c b/ports/nrf/modules/machine/i2c.c index 1d8971612169d..6ec902a833752 100644 --- a/ports/nrf/modules/machine/i2c.c +++ b/ports/nrf/modules/machine/i2c.c @@ -31,11 +31,33 @@ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" + +#if MICROPY_PY_MACHINE_I2C + #include "extmod/machine_i2c.h" #include "i2c.h" +#if NRFX_TWI_ENABLED #include "nrfx_twi.h" +#else +#include "nrfx_twim.h" +#endif -#if MICROPY_PY_MACHINE_I2C +#if NRFX_TWIM_ENABLED + +#define nrfx_twi_t nrfx_twim_t +#define nrfx_twi_config_t nrfx_twim_config_t + +#define nrfx_twi_init nrfx_twim_init +#define nrfx_twi_enable nrfx_twim_enable +#define nrfx_twi_rx nrfx_twim_rx +#define nrfx_twi_tx nrfx_twim_tx +#define nrfx_twi_disable nrfx_twim_disable + +#define NRFX_TWI_INSTANCE NRFX_TWIM_INSTANCE + +#define NRF_TWI_FREQ_400K NRF_TWIM_FREQ_400K + +#endif STATIC const mp_obj_type_t machine_hard_i2c_type; From 02a8c31eef3778941da378b315033d6fde19c73c Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Sun, 23 Dec 2018 16:23:32 +0100 Subject: [PATCH 0509/1299] nrf/temp: Move module configuration guard. This patch moves the check for MICROPY_PY_MACHINE_TEMP to come before the inclusion of nrf_temp.h. The nrf_temp.h depends on the NRF_TEMP_Type which might not be defined for all nRF devices. --- ports/nrf/modules/machine/temp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ports/nrf/modules/machine/temp.c b/ports/nrf/modules/machine/temp.c index 007a7e5fd8e95..047514967f69c 100644 --- a/ports/nrf/modules/machine/temp.c +++ b/ports/nrf/modules/machine/temp.c @@ -30,6 +30,9 @@ #include "py/nlr.h" #include "py/runtime.h" #include "py/mphal.h" + +#if MICROPY_PY_MACHINE_TEMP + #include "temp.h" #include "nrf_temp.h" @@ -40,8 +43,6 @@ #define BLUETOOTH_STACK_ENABLED() (ble_drv_stack_enabled()) #endif // BLUETOOTH_SD -#if MICROPY_PY_MACHINE_TEMP - typedef struct _machine_temp_obj_t { mp_obj_base_t base; } machine_temp_obj_t; From c561ae61a11afd22379bfd5f688cd4d8c9292ba7 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Sun, 23 Dec 2018 16:31:23 +0100 Subject: [PATCH 0510/1299] nrf/uart: Add support for UARTE (EasyDMA). --- ports/nrf/modules/machine/uart.c | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c index b9c018fc84168..5f7daa91e90c8 100644 --- a/ports/nrf/modules/machine/uart.c +++ b/ports/nrf/modules/machine/uart.c @@ -44,7 +44,12 @@ #include "mpconfigboard.h" #include "nrf.h" #include "mphalport.h" + +#if NRFX_UART_ENABLED #include "nrfx_uart.h" +#else +#include "nrfx_uarte.h" +#endif #if MICROPY_PY_MACHINE_UART @@ -56,6 +61,40 @@ typedef struct _machine_hard_uart_buf_t { volatile ringbuf_t rx_ringbuf; } machine_hard_uart_buf_t; +#if NRFX_UARTE_ENABLED + +#define nrfx_uart_t nrfx_uarte_t +#define nrfx_uart_config_t nrfx_uarte_config_t + +#define nrfx_uart_rx nrfx_uarte_rx +#define nrfx_uart_tx nrfx_uarte_tx +#define nrfx_uart_tx_in_progress nrfx_uarte_tx_in_progress +#define nrfx_uart_init nrfx_uarte_init +#define nrfx_uart_event_t nrfx_uarte_event_t +#define NRFX_UART_INSTANCE NRFX_UARTE_INSTANCE + +#define NRF_UART_HWFC_ENABLED NRF_UARTE_HWFC_ENABLED +#define NRF_UART_HWFC_DISABLED NRF_UARTE_HWFC_DISABLED +#define NRF_UART_PARITY_EXCLUDED NRF_UARTE_PARITY_EXCLUDED +#define NRFX_UART_EVT_RX_DONE NRFX_UARTE_EVT_RX_DONE + +#define NRF_UART_BAUDRATE_1200 NRF_UARTE_BAUDRATE_1200 +#define NRF_UART_BAUDRATE_2400 NRF_UARTE_BAUDRATE_2400 +#define NRF_UART_BAUDRATE_4800 NRF_UARTE_BAUDRATE_4800 +#define NRF_UART_BAUDRATE_9600 NRF_UARTE_BAUDRATE_9600 +#define NRF_UART_BAUDRATE_14400 NRF_UARTE_BAUDRATE_14400 +#define NRF_UART_BAUDRATE_19200 NRF_UARTE_BAUDRATE_19200 +#define NRF_UART_BAUDRATE_28800 NRF_UARTE_BAUDRATE_28800 +#define NRF_UART_BAUDRATE_38400 NRF_UARTE_BAUDRATE_38400 +#define NRF_UART_BAUDRATE_57600 NRF_UARTE_BAUDRATE_57600 +#define NRF_UART_BAUDRATE_76800 NRF_UARTE_BAUDRATE_76800 +#define NRF_UART_BAUDRATE_115200 NRF_UARTE_BAUDRATE_115200 +#define NRF_UART_BAUDRATE_230400 NRF_UARTE_BAUDRATE_230400 +#define NRF_UART_BAUDRATE_250000 NRF_UARTE_BAUDRATE_250000 +#define NRF_UART_BAUDRATE_1000000 NRF_UARTE_BAUDRATE_1000000 + +#endif + typedef struct _machine_hard_uart_obj_t { mp_obj_base_t base; const nrfx_uart_t * p_uart; // Driver instance @@ -210,7 +249,10 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a // Enable event callback and start asynchronous receive nrfx_uart_init(self->p_uart, &config, uart_event_handler); nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1); + +#if NRFX_UART_ENABLED nrfx_uart_rx_enable(self->p_uart); +#endif return MP_OBJ_FROM_PTR(self); } From cf383412efab088ab448ec22c838d483f4d082de Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Wed, 3 Apr 2019 23:51:38 +0200 Subject: [PATCH 0511/1299] nrf/flash: Update flash driver to use nrfx_nvmc driver. The the nrfx driver is aware of chip specific registers, while the raw HAL abstraction is not. This driver enables use of NVMC in non-secure domain for nrf9160. --- ports/nrf/Makefile | 5 +---- ports/nrf/drivers/flash.h | 8 ++++---- ports/nrf/nrfx_config.h | 2 ++ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index c02109a156225..1b70851eb868d 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -181,10 +181,7 @@ SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ nrfx_timer.c \ nrfx_pwm.c \ nrfx_gpiote.c \ - ) - -SRC_NRFX_HAL += $(addprefix lib/nrfx/hal/,\ - nrf_nvmc.c \ + nrfx_nvmc.c \ ) SRC_C += \ diff --git a/ports/nrf/drivers/flash.h b/ports/nrf/drivers/flash.h index 7e6fff37a97bb..3dd5d06dd4e75 100644 --- a/ports/nrf/drivers/flash.h +++ b/ports/nrf/drivers/flash.h @@ -27,7 +27,7 @@ #ifndef __MICROPY_INCLUDED_LIB_FLASH_H__ #define __MICROPY_INCLUDED_LIB_FLASH_H__ -#include "nrf_nvmc.h" +#include "nrfx_nvmc.h" #if defined(NRF51) #define FLASH_PAGESIZE (1024) @@ -55,9 +55,9 @@ void flash_operation_finished(flash_state_t result); #else -#define flash_page_erase nrf_nvmc_page_erase -#define flash_write_byte nrf_nvmc_write_byte -#define flash_write_bytes nrf_nvmc_write_bytes +#define flash_page_erase nrfx_nvmc_page_erase +#define flash_write_byte nrfx_nvmc_byte_write +#define flash_write_bytes nrfx_nvmc_bytes_write #endif diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index d8a7d521dae9d..99085a2fe86ba 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -103,6 +103,8 @@ #define NRFX_PWM2_ENABLED 1 #define NRFX_PWM3_ENABLED (NRF52840) +#define NRFX_NVMC_ENABLED 1 + // Peripheral Resource Sharing #if defined(NRF51) || defined(NRF52832) #define NRFX_PRS_BOX_0_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI0_ENABLED && NRFX_SPI_ENABLED && NRFX_SPI0_ENABLED) From 226399bcef8abf2f831cdb139c9bd0d416850ab5 Mon Sep 17 00:00:00 2001 From: roland van straten Date: Fri, 27 Sep 2019 09:55:58 +0200 Subject: [PATCH 0512/1299] nrf/led: Expose public API for LED manipulation. Aligned implementation with the STM32 port. Added empty functions to be used when no LED is available. --- ports/nrf/modules/board/led.c | 29 +++++++++++++++++++---------- ports/nrf/modules/board/led.h | 2 ++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/ports/nrf/modules/board/led.c b/ports/nrf/modules/board/led.c index 5d7b54ecba78e..a7efafa366022 100644 --- a/ports/nrf/modules/board/led.c +++ b/ports/nrf/modules/board/led.c @@ -65,8 +65,8 @@ static const board_led_obj_t board_led_obj[] = { #if MICROPY_HW_LED_TRICOLOR {{&board_led_type}, BOARD_LED_RED, MICROPY_HW_LED_RED, 0, MICROPY_HW_LED_PULLUP}, - {{&board_led_type}, BOARD_LED_GREEN, MICROPY_HW_LED_GREEN,0, MICROPY_HW_LED_PULLUP}, - {{&board_led_type}, BOARD_LED_BLUE, MICROPY_HW_LED_BLUE,0, MICROPY_HW_LED_PULLUP}, + {{&board_led_type}, BOARD_LED_GREEN, MICROPY_HW_LED_GREEN, 0, MICROPY_HW_LED_PULLUP}, + {{&board_led_type}, BOARD_LED_BLUE, MICROPY_HW_LED_BLUE, 0, MICROPY_HW_LED_PULLUP}, #endif #if (MICROPY_HW_LED_COUNT >= 1) {{&board_led_type}, BOARD_LED1, MICROPY_HW_LED1, 0, @@ -115,17 +115,17 @@ void led_init(void) { } } -void led_state(board_led_obj_t * led_obj, int state) { +void led_state(board_led_t led, int state) { if (state == 1) { - led_on(led_obj); + led_on((board_led_obj_t*)&board_led_obj[led-1]); } else { - led_off(led_obj); + led_off((board_led_obj_t*)&board_led_obj[led-1]); } } -void led_toggle(board_led_obj_t * led_obj) { - nrf_gpio_pin_toggle(led_obj->hw_pin); +void led_toggle(board_led_t led) { + nrf_gpio_pin_toggle(board_led_obj[led-1].hw_pin); } @@ -162,7 +162,7 @@ STATIC mp_obj_t led_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_ /// Turn the LED on. mp_obj_t led_obj_on(mp_obj_t self_in) { board_led_obj_t *self = self_in; - led_state(self, 1); + led_state(self->led_id, 1); return mp_const_none; } @@ -170,7 +170,7 @@ mp_obj_t led_obj_on(mp_obj_t self_in) { /// Turn the LED off. mp_obj_t led_obj_off(mp_obj_t self_in) { board_led_obj_t *self = self_in; - led_state(self, 0); + led_state(self->led_id, 0); return mp_const_none; } @@ -178,7 +178,7 @@ mp_obj_t led_obj_off(mp_obj_t self_in) { /// Toggle the LED between on and off. mp_obj_t led_obj_toggle(mp_obj_t self_in) { board_led_obj_t *self = self_in; - led_toggle(self); + led_toggle(self->led_id); return mp_const_none; } @@ -202,4 +202,13 @@ const mp_obj_type_t board_led_type = { .locals_dict = (mp_obj_dict_t*)&led_locals_dict, }; +#else +// For boards with no LEDs, we leave an empty function here so that we don't +// have to put conditionals everywhere. +void led_init(void) { +} +void led_state(board_led_t led, int state) { +} +void led_toggle(board_led_t led) { +} #endif // MICROPY_HW_HAS_LED diff --git a/ports/nrf/modules/board/led.h b/ports/nrf/modules/board/led.h index 537b9ac546ad3..187752189f1d3 100644 --- a/ports/nrf/modules/board/led.h +++ b/ports/nrf/modules/board/led.h @@ -51,6 +51,8 @@ typedef enum { } board_led_t; void led_init(void); +void led_state(board_led_t, int); +void led_toggle(board_led_t); extern const mp_obj_type_t board_led_type; From a069340c1ee14fe5e956e38aa4482f526145d7d3 Mon Sep 17 00:00:00 2001 From: roland van straten Date: Fri, 27 Sep 2019 09:58:21 +0200 Subject: [PATCH 0513/1299] nrf/main: Update the way the LED is used on startup. In case of LED1 being present, do a short blink during startup instead of turning it on and leave it on. --- ports/nrf/main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 38d41bd8c523a..e82cfcf58dd56 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -95,7 +95,13 @@ extern uint32_t _heap_end; int main(int argc, char **argv) { + soft_reset: + + led_init(); + + led_state(1, 1); // MICROPY_HW_LED_1 aka MICROPY_HW_LED_RED + mp_stack_set_top(&_ram_end); // Stack limit should be less than real stack size, so we have a chance @@ -192,14 +198,6 @@ pin_init0(); } #endif -#if (MICROPY_HW_HAS_LED) - led_init(); - - do_str("import board\r\n" \ - "board.LED(1).on()", - MP_PARSE_FILE_INPUT); -#endif - // Main script is finished, so now go into REPL mode. // The REPL mode can change, or it can request a soft reset. int ret_code = 0; @@ -225,6 +223,8 @@ pin_init0(); pwm_start(); #endif +led_state(1, 0); + #if MICROPY_VFS || MICROPY_MBFS // run boot.py and main.py if they exist. pyexec_file_if_exists("boot.py"); From 266146ad643b408a307676e320ffb22e0fe1e0ad Mon Sep 17 00:00:00 2001 From: hahmadi Date: Sat, 21 Sep 2019 13:30:19 -0400 Subject: [PATCH 0514/1299] stm32/system_stm32: Support selection of HSE and LSI on L4 MCUs. This commit adds the option to use HSE or MSI system clock, and LSE or LSI RTC clock, on L4 MCUs. Note that prior to this commit the default clocks on an L4 part were MSI and LSE. The defaults are now MSI and LSI. In mpconfigboard.h select the clock source via: #define MICROPY_HW_RTC_USE_LSE (0) or (1) #define MICROPY_HW_CLK_USE_HSE (0) or (1) and the PLLSAI1 N,P,Q,R settings: #define MICROPY_HW_CLK_PLLSAIN (12) #define MICROPY_HW_CLK_PLLSAIP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLSAIQ (RCC_PLLQ_DIV2) #define MICROPY_HW_CLK_PLLSAIR (RCC_PLLR_DIV2) --- ports/stm32/system_stm32.c | 45 +++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index 0792d124d6153..46dd58ba2fda2 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -213,12 +213,31 @@ void SystemClock_Config(void) #endif RCC_OscInitStruct.PLL.PLLSource = MICROPY_HW_RCC_PLL_SRC; #elif defined(STM32L4) + + #if MICROPY_HW_CLK_USE_HSE + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = MICROPY_HW_CLK_PLLM; + RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN; + RCC_OscInitStruct.PLL.PLLP = MICROPY_HW_CLK_PLLP; + RCC_OscInitStruct.PLL.PLLQ = MICROPY_HW_CLK_PLLQ; + RCC_OscInitStruct.PLL.PLLR = MICROPY_HW_CLK_PLLR; + RCC_OscInitStruct.MSIState = RCC_MSI_OFF; + #else RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.MSIState = RCC_MSI_ON; RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; + #endif + + #if MICROPY_HW_RTC_USE_LSE + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + #else + RCC_OscInitStruct.LSEState = RCC_LSE_OFF; + #endif + #endif RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 @@ -362,20 +381,36 @@ void SystemClock_Config(void) |RCC_PERIPHCLK_USB |RCC_PERIPHCLK_ADC |RCC_PERIPHCLK_RNG |RCC_PERIPHCLK_RTC; PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; - /* PLLSAI is used to clock USB, ADC, I2C1 and RNG. The frequency is - MSI(4MHz)/PLLM(1)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz. See the STM32CubeMx - application or the reference manual. */ + PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1; PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1; - PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1; + + #if MICROPY_HW_RTC_USE_LSE + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + #else + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; + #endif + + #if MICROPY_HW_CLK_USE_HSE + PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE; + PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 1; //MICROPY_HW_CLK_PLLSAIM; + PeriphClkInitStruct.PLLSAI1.PLLSAI1N = MICROPY_HW_CLK_PLLSAIN; + PeriphClkInitStruct.PLLSAI1.PLLSAI1P = MICROPY_HW_CLK_PLLSAIP; + PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = MICROPY_HW_CLK_PLLSAIQ; + PeriphClkInitStruct.PLLSAI1.PLLSAI1R = MICROPY_HW_CLK_PLLSAIR; + #else + /* PLLSAI is used to clock USB, ADC, I2C1 and RNG. The frequency is + MSI(4MHz)/PLLM(1)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz. See the STM32CubeMx + application or the reference manual. */ PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_MSI; PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 1; PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24; PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7; PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2; PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2; + #endif PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK |RCC_PLLSAI1_48M2CLK |RCC_PLLSAI1_ADC1CLK; From 26e90a051415629796efbec59f1d653b46e43aea Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 4 Oct 2019 16:03:37 +1000 Subject: [PATCH 0515/1299] stm32/boards: Enable MICROPY_HW_RTC_USE_LSE on L4 boards. The previous commit changed the default configuration on L4 MCUs to use LSI, so configure these boards to use LSE again. --- ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h | 4 +++- ports/stm32/boards/LIMIFROG/mpconfigboard.h | 4 +++- ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h | 3 +++ ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h | 3 +++ ports/stm32/boards/STM32L496GDISC/mpconfigboard.h | 4 +++- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h b/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h index 3ab3d5fa1719d..a88bcf675685e 100644 --- a/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h +++ b/ports/stm32/boards/B_L475E_IOT01A/mpconfigboard.h @@ -12,9 +12,11 @@ #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV4) - #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 +// The board has an external 32kHz crystal +#define MICROPY_HW_RTC_USE_LSE (1) + // USART1 config connected to ST-Link #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) diff --git a/ports/stm32/boards/LIMIFROG/mpconfigboard.h b/ports/stm32/boards/LIMIFROG/mpconfigboard.h index d27c2e66ef77d..4b750c17ff4f6 100644 --- a/ports/stm32/boards/LIMIFROG/mpconfigboard.h +++ b/ports/stm32/boards/LIMIFROG/mpconfigboard.h @@ -16,9 +16,11 @@ void LIMIFROG_board_early_init(void); #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) - #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 +// The board has an external 32kHz crystal +#define MICROPY_HW_RTC_USE_LSE (1) + // USART config #define MICROPY_HW_UART3_TX (pin_C10) #define MICROPY_HW_UART3_RX (pin_C11) diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h index 60e053f44fa1c..e7202efe02c11 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h @@ -25,6 +25,9 @@ #define MICROPY_HW_CLK_PLLP (7) #define MICROPY_HW_CLK_PLLQ (2) +// The board has an external 32kHz crystal +#define MICROPY_HW_RTC_USE_LSE (1) + // UART config #define MICROPY_HW_UART1_TX (pin_B6) #define MICROPY_HW_UART1_RX (pin_B7) diff --git a/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h index 05298253ae059..00b033006ba9a 100644 --- a/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L476RG/mpconfigboard.h @@ -15,6 +15,9 @@ #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) +// The board has an external 32kHz crystal +#define MICROPY_HW_RTC_USE_LSE (1) + // UART config #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_A3) diff --git a/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h b/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h index 6a17d74d3a016..5d9fa25bc3b84 100644 --- a/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32L496GDISC/mpconfigboard.h @@ -14,9 +14,11 @@ #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7) #define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2) #define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2) - #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 +// The board has an external 32kHz crystal +#define MICROPY_HW_RTC_USE_LSE (1) + // USART config #define MICROPY_HW_UART2_TX (pin_A2) #define MICROPY_HW_UART2_RX (pin_D6) From 25a9bccdee2fe830046c1c1a0220ca7706597202 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 20 Sep 2019 09:16:34 +0200 Subject: [PATCH 0516/1299] py/compile: Disallow 'import *' outside module level. This check follows CPython's behaviour, because 'import *' always populates the globals with the imported names, not locals. Since it's safe to do this (doesn't lead to a crash or undefined behaviour) the check is only enabled for MICROPY_CPYTHON_COMPAT. Fixes issue #5121. --- py/compile.c | 7 +++++++ tests/cmdline/cmd_showbc.py | 5 ++++- tests/cmdline/cmd_showbc.py.exp | 12 ++++++------ tests/import/import_star_error.py | 13 +++++++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 tests/import/import_star_error.py diff --git a/py/compile.c b/py/compile.c index 90d1bfd138899..62b0f3938df7d 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1196,6 +1196,13 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { } while (0); if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) { + #if MICROPY_CPYTHON_COMPAT + if (comp->scope_cur->kind != SCOPE_MODULE) { + compile_syntax_error(comp, (mp_parse_node_t)pns, "import * not at module level"); + return; + } + #endif + EMIT_ARG(load_const_small_int, import_level); // build the "fromlist" tuple diff --git a/tests/cmdline/cmd_showbc.py b/tests/cmdline/cmd_showbc.py index 916228356fb3e..f30b39ee108af 100644 --- a/tests/cmdline/cmd_showbc.py +++ b/tests/cmdline/cmd_showbc.py @@ -115,7 +115,7 @@ def closure(): # import import a from a import b - from a import * + #from sys import * # tested at module scope # raise raise @@ -154,3 +154,6 @@ class Class: # load super method def f(self): super().f() + +# import * (needs to be in module scope) +from sys import * diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index b0a9016c517cb..4d90ae22cae33 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -7,7 +7,7 @@ arg names: (N_EXC_STACK 0) bc=0 line=1 ######## - bc=\\d\+ line=155 + bc=\\d\+ line=159 00 MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f \\d\+ MAKE_FUNCTION \.\+ @@ -27,6 +27,11 @@ arg names: \\d\+ DELETE_NAME Class \\d\+ MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f +\\d\+ LOAD_CONST_SMALL_INT 0 +\\d\+ LOAD_CONST_STRING '*' +\\d\+ BUILD_TUPLE 1 +\\d\+ IMPORT_NAME 'sys' +\\d\+ IMPORT_STAR \\d\+ LOAD_CONST_NONE \\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) @@ -300,11 +305,6 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ IMPORT_FROM 'b' \\d\+ STORE_DEREF 14 \\d\+ POP_TOP -\\d\+ LOAD_CONST_SMALL_INT 0 -\\d\+ LOAD_CONST_STRING '*' -\\d\+ BUILD_TUPLE 1 -\\d\+ IMPORT_NAME 'a' -\\d\+ IMPORT_STAR \\d\+ RAISE_LAST \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ RAISE_OBJ diff --git a/tests/import/import_star_error.py b/tests/import/import_star_error.py new file mode 100644 index 0000000000000..17e237b8c1434 --- /dev/null +++ b/tests/import/import_star_error.py @@ -0,0 +1,13 @@ +# test errors with import * + +# 'import *' is not allowed in function scope +try: + exec('def foo(): from x import *') +except SyntaxError as er: + print('function', 'SyntaxError') + +# 'import *' is not allowed in class scope +try: + exec('class C: from x import *') +except SyntaxError as er: + print('class', 'SyntaxError') From 4ddd46e6cfd1f10efbd6fbbbc0fed520a1058045 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 26 Sep 2019 20:25:39 +1000 Subject: [PATCH 0517/1299] docs/develop/qstr.rst: Add documentation for string interning. --- docs/develop/index.rst | 1 + docs/develop/qstr.rst | 112 +++++++++++++++++++++++++++++++++++++++++ py/mkrules.mk | 1 + py/py.mk | 1 + 4 files changed, 115 insertions(+) create mode 100644 docs/develop/qstr.rst diff --git a/docs/develop/index.rst b/docs/develop/index.rst index 64dbc4661382e..fff3e43d74824 100644 --- a/docs/develop/index.rst +++ b/docs/develop/index.rst @@ -10,3 +10,4 @@ See the `getting started guide :maxdepth: 1 cmodules.rst + qstr.rst diff --git a/docs/develop/qstr.rst b/docs/develop/qstr.rst new file mode 100644 index 0000000000000..1b3b9f903bc91 --- /dev/null +++ b/docs/develop/qstr.rst @@ -0,0 +1,112 @@ +MicroPython string interning +============================ + +MicroPython uses `string interning`_ to save both RAM and ROM. This avoids +having to store duplicate copies of the same string. Primarily, this applies to +identifiers in your code, as something like a function or variable name is very +likely to appear in multiple places in the code. In MicroPython an interned +string is called a QSTR (uniQue STRing). + +A QSTR value (with type ``qstr``) is a index into a linked list of QSTR pools. +QSTRs store their length and a hash of their contents for fast comparison during +the de-duplication process. All bytecode operations that work with strings use +a QSTR argument. + +Compile-time QSTR generation +---------------------------- + +In the MicroPython C code, any strings that should be interned in the final +firmware are written as ``MP_QSTR_Foo``. At compile time this will evaluate to +a ``qstr`` value that points to the index of ``"Foo"`` in the QSTR pool. + +A multi-step process in the ``Makefile`` makes this work. In summary this +process has three parts: + +1. Find all ``MP_QSTR_Foo`` tokens in the code. + +2. Generate a static QSTR pool containing all the string data (including lengths + and hashes). + +3. Replace all ``MP_QSTR_Foo`` (via the preprocessor) with their corresponding + index. + +``MP_QSTR_Foo`` tokens are searched for in two sources: + +1. All files referenced in ``$(SRC_QSTR)``. This is all C code (i.e. ``py``, + ``extmod``, ``ports/stm32``) but not including third-party code such as + ``lib``. + +2. Additional ``$(QSTR_GLOBAL_DEPENDENCIES)`` (which includes ``mpconfig*.h``). + +*Note:* ``frozen_mpy.c`` (generated by mpy-tool.py) has its own QSTR generation +and pool. + +Some additional strings that can't be expressed using the ``MP_QSTR_Foo`` syntax +(e.g. they contain non-alphanumeric characters) are explicitly provided in +``qstrdefs.h`` and ``qstrdefsport.h`` via the ``$(QSTR_DEFS)`` variable. + +Processing happens in the following stages: + +1. ``qstr.i.last`` is the concatenation of putting every single input file + through the C pre-processor. This means that any conditionally disabled code + will be removed, and macros expanded. This means we don't add strings to the + pool that won't be used in the final firmware. Because at this stage (thanks + to the ``NO_QSTR`` macro added by ``QSTR_GEN_EXTRA_CFLAGS``) there is no + definition for ``MP_QSTR_Foo`` it passes through this stage unaffected. This + file also includes comments from the preprocessor that include line number + information. Note that this step only uses files that have changed, which + means that ``qstr.i.last`` will only contain data from files that have + changed since the last compile. +2. ``qstr.split`` is an empty file created after running ``makeqstrdefs.py split`` + on qstr.i.last. It's just used as a dependency to indicate that the step ran. + This script outputs one file per input C file, ``genhdr/qstr/...file.c.qstr``, + which contains only the matched QSTRs. Each QSTR is printed as ``Q(Foo)``. + This step is necessary to combine the existing files with the new data + generated from the incremental update in ``qstr.i.last``. + +3. ``qstrdefs.collected.h`` is the output of concatenating ``genhdr/qstr/*`` + using ``makeqstrdefs.py cat``. This is now the full set of ``MP_QSTR_Foo``'s + found in the code, now formatted as ``Q(Foo)``, one-per-line, with duplicates. + This file is only updated if the set of qstrs has changed. A hash of the QSTR + data is written to another file (``qstrdefs.collected.h.hash``) which allows + it to track changes across builds. + +4. ``qstrdefs.preprocessed.h`` adds in the QSTRs from qstrdefs*. It + concatenates ``qstrdefs.collected.h`` with ``qstrdefs*.h``, then it transforms + each line from ``Q(Foo)`` to ``"Q(Foo)"`` so they pass through the preprocessor + unchanged. Then the preprocessor is used to deal with any conditional + compilation in ``qstrdefs*.h``. Then the transformation is undone back to + ``Q(Foo)``, and saved as ``qstrdefs.preprocessed.h``. + +5. ``qstrdefs.generated.h`` is the output of ``makeqstrdata.py``. For each + ``Q(Foo)`` in qstrdefs.preprocessed.h (plus some extra hard-coded ones), it outputs + ``QDEF(MP_QSTR_Foo, (const byte*)"hash" "Foo")``. + +Then in the main compile, two things happen with ``qstrdefs.generated.h``: + +1. In qstr.h, each QDEF becomes an entry in an enum, which makes ``MP_QSTR_Foo`` + available to code and equal to the index of that string in the QSTR table. + +2. In qstr.c, the actual QSTR data table is generated as elements of the + ``mp_qstr_const_pool->qstrs``. + +.. _`string interning`: https://en.wikipedia.org/wiki/String_interning + +Run-time QSTR generation +------------------------ + +Additional QSTR pools can be created at runtime so that strings can be added to +them. For example, the code:: + + foo[x] = 3 + +Will need to create a QSTR for the value of ``x`` so it can be used by the +"load attr" bytecode. + +Also, when compiling Python code, identifiers and literals need to have QSTRs +created. Note: only literals shorter than 10 characters become QSTRs. This is +because a regular string on the heap always takes up a minimum of 16 bytes (one +GC block), whereas QSTRs allow them to be packed more efficiently into the pool. + +QSTR pools (and the underlying "chunks" that store the string data) are allocated +on-demand on the heap with a minimum size. diff --git a/py/mkrules.mk b/py/mkrules.mk index b74dd4549528a..f9d77c3177afe 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -70,6 +70,7 @@ $(OBJ): | $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/mpversion.h # - if anything in QSTR_GLOBAL_DEPENDENCIES is newer, then process all source files ($^) # - else, if list of newer prerequisites ($?) is not empty, then process just these ($?) # - else, process all source files ($^) [this covers "make -B" which can set $? to empty] +# See more information about this process in docs/develop/qstr.rst. $(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(QSTR_GLOBAL_DEPENDENCIES) | $(QSTR_GLOBAL_REQUIREMENTS) $(ECHO) "GEN $@" $(Q)$(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) >$(HEADER_BUILD)/qstr.i.last diff --git a/py/py.mk b/py/py.mk index ba3a8639bf61a..d97852dd431b7 100644 --- a/py/py.mk +++ b/py/py.mk @@ -231,6 +231,7 @@ MPCONFIGPORT_MK = $(wildcard mpconfigport.mk) # created before we run the script to generate the .h # Note: we need to protect the qstr names from the preprocessor, so we wrap # the lines in "" and then unwrap after the preprocessor is finished. +# See more information about this process in docs/develop/qstr.rst. $(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) $(PY_SRC)/makeqstrdata.py mpconfigport.h $(MPCONFIGPORT_MK) $(PY_SRC)/mpconfig.h | $(HEADER_BUILD) $(ECHO) "GEN $@" $(Q)$(CAT) $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | $(SED) 's/^\"\(Q(.*)\)\"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h From a09fd0475840ae6a24995ab7ab7955c88289817a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 26 Sep 2019 20:41:41 +1000 Subject: [PATCH 0518/1299] py/makeqstrdefs.py: Remove unused blacklist. As of 7d58a197cffa7c0dd3686402d2e381812bb8ddeb, `NULL` should no longer be here because it's allowed (MP_QSTRnull took its place). This entry was preventing the use of MP_QSTR_NULL to mean "NULL" (although this is not currently used). A blacklist should not be needed because it should be possible to intern all strings. Fixes issue #5140. --- py/makeqstrdefs.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 457bdeef65dbf..209e7a132dd9d 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -12,10 +12,6 @@ import io import os -# Blacklist of qstrings that are specially handled in further -# processing and should be ignored -QSTRING_BLACK_LIST = set(['NULL', 'number_of']) - def write_out(fname, output): if output: @@ -46,8 +42,7 @@ def process_file(f): continue for match in re_qstr.findall(line): name = match.replace('MP_QSTR_', '') - if name not in QSTRING_BLACK_LIST: - output.append('Q(' + name + ')') + output.append('Q(' + name + ')') write_out(last_fname, output) return "" From 0096041c9912d34a6227f647c264325b178c0384 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 27 Sep 2019 14:27:51 +1000 Subject: [PATCH 0519/1299] stm32/{adc,machine_adc}: Change ADC clock and sampling time for F0 MCUs. STM32F0 has PCLK=48MHz and maximum ADC clock is 14MHz so use PCLK/4=12MHz to stay within spec of the ADC peripheral. In pyb.ADC set common sampling time to approx 4uS for internal and external sources. In machine.ADC reduce sample time to approx 1uS for external source, leave internal at maximum sampling time. --- ports/stm32/adc.c | 14 ++++++++------ ports/stm32/machine_adc.c | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index a4eaefd7589b7..11b15cd09a2c6 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -241,7 +241,13 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { adch->Init.EOCSelection = ADC_EOC_SINGLE_CONV; adch->Init.ExternalTrigConv = ADC_SOFTWARE_START; adch->Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) + #if defined(STM32F0) + adch->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 12MHz + adch->Init.ScanConvMode = DISABLE; + adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; + adch->Init.DMAContinuousRequests = DISABLE; + adch->Init.SamplingTimeCommon = ADC_SAMPLETIME_55CYCLES_5; // ~4uS + #elif defined(STM32F4) || defined(STM32F7) adch->Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; adch->Init.ScanConvMode = DISABLE; adch->Init.DataAlign = ADC_DATAALIGN_RIGHT; @@ -266,10 +272,6 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { #error Unsupported processor #endif - #if defined(STM32F0) - adch->Init.SamplingTimeCommon = ADC_SAMPLETIME_71CYCLES_5; - #endif - HAL_ADC_Init(adch); #if defined(STM32H7) @@ -309,7 +311,7 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.Channel = channel; sConfig.Rank = 1; #if defined(STM32F0) - sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5; + sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; #elif defined(STM32F4) || defined(STM32F7) sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; #elif defined(STM32H7) diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 3aacae77babef..22e60f043e6cb 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -49,7 +49,7 @@ #endif #if defined(STM32F0) -#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_71CYCLES_5 +#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_13CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_239CYCLES_5 #elif defined(STM32F4) || defined(STM32F7) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_15CYCLES @@ -126,7 +126,7 @@ STATIC void adc_config(ADC_TypeDef *adc, uint32_t bits) { // Configure clock mode #if defined(STM32F0) - adc->CFGR2 = 1 << ADC_CFGR2_CKMODE_Pos; // PCLK/2 (synchronous clock mode) + adc->CFGR2 = 2 << ADC_CFGR2_CKMODE_Pos; // PCLK/4 (synchronous clock mode) #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L4) ADCx_COMMON->CCR = 0; // ADCPR=PCLK/2 #elif defined(STM32H7) From 82c494a97e874912e7eb23d2f03f39212e343fb3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 28 Sep 2019 00:07:21 +1000 Subject: [PATCH 0520/1299] py/vm: Fix handling of unwind jump out of active finally. Prior to this commit, when unwinding through an active finally the stack was not being correctly popped/folded, which resulting in the VM crashing for complicated unwinding of nested finallys. This should be fixed with this commit, and more tests for return/break/ continue within a finally have been added to exercise this. --- py/vm.c | 104 ++++++++++++++--------- tests/basics/try_finally_break2.py | 19 +++++ tests/basics/try_finally_continue.py | 17 ++++ tests/basics/try_finally_continue.py.exp | 9 ++ tests/basics/try_finally_return5.py | 17 ++++ 5 files changed, 127 insertions(+), 39 deletions(-) create mode 100644 tests/basics/try_finally_break2.py create mode 100644 tests/basics/try_finally_continue.py create mode 100644 tests/basics/try_finally_continue.py.exp create mode 100644 tests/basics/try_finally_return5.py diff --git a/py/vm.c b/py/vm.c index 7487ff61b4fff..6e5015fc4310b 100644 --- a/py/vm.c +++ b/py/vm.c @@ -109,6 +109,21 @@ exc_sp--; /* pop back to previous exception handler */ \ CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */ +#define CANCEL_ACTIVE_FINALLY(sp) do { \ + if (mp_obj_is_small_int(sp[-1])) { \ + /* Stack: (..., prev_dest_ip, prev_cause, dest_ip) */ \ + /* Cancel the unwind through the previous finally, replace with current one */ \ + sp[-2] = sp[0]; \ + sp -= 2; \ + } else { \ + assert(sp[-1] == mp_const_none || mp_obj_is_exception_instance(sp[-1])); \ + /* Stack: (..., None/exception, dest_ip) */ \ + /* Silence the finally's exception value (may be None or an exception) */ \ + sp[-1] = sp[0]; \ + --sp; \ + } \ +} while (0) + #if MICROPY_PY_SYS_SETTRACE #define FRAME_SETUP() do { \ @@ -698,21 +713,28 @@ unwind_jump:; while ((unum & 0x7f) > 0) { unum -= 1; assert(exc_sp >= exc_stack); - if (MP_TAGPTR_TAG1(exc_sp->val_sp) && exc_sp->handler > ip) { - // Getting here the stack looks like: - // (..., X, dest_ip) - // where X is pointed to by exc_sp->val_sp and in the case - // of a "with" block contains the context manager info. - // We're going to run "finally" code as a coroutine - // (not calling it recursively). Set up a sentinel - // on the stack so it can return back to us when it is - // done (when WITH_CLEANUP or END_FINALLY reached). - // The sentinel is the number of exception handlers left to - // unwind, which is a non-negative integer. - PUSH(MP_OBJ_NEW_SMALL_INT(unum)); - ip = exc_sp->handler; // get exception handler byte code address - exc_sp--; // pop exception handler - goto dispatch_loop; // run the exception handler + + if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { + if (exc_sp->handler > ip) { + // Found a finally handler that isn't active; run it. + // Getting here the stack looks like: + // (..., X, dest_ip) + // where X is pointed to by exc_sp->val_sp and in the case + // of a "with" block contains the context manager info. + assert(&sp[-1] == MP_TAGPTR_PTR(exc_sp->val_sp)); + // We're going to run "finally" code as a coroutine + // (not calling it recursively). Set up a sentinel + // on the stack so it can return back to us when it is + // done (when WITH_CLEANUP or END_FINALLY reached). + // The sentinel is the number of exception handlers left to + // unwind, which is a non-negative integer. + PUSH(MP_OBJ_NEW_SMALL_INT(unum)); + ip = exc_sp->handler; + goto dispatch_loop; + } else { + // Found a finally handler that is already active; cancel it. + CANCEL_ACTIVE_FINALLY(sp); + } } POP_EXC_BLOCK(); } @@ -740,9 +762,9 @@ unwind_jump:; // if TOS is None, just pops it and continues // if TOS is an integer, finishes coroutine and returns control to caller // if TOS is an exception, reraises the exception + assert(exc_sp >= exc_stack); + POP_EXC_BLOCK(); if (TOP() == mp_const_none) { - assert(exc_sp >= exc_stack); - POP_EXC_BLOCK(); sp--; } else if (mp_obj_is_small_int(TOP())) { // We finished "finally" coroutine and now dispatch back @@ -1113,28 +1135,32 @@ unwind_jump:; unwind_return: // Search for and execute finally handlers that aren't already active while (exc_sp >= exc_stack) { - if (MP_TAGPTR_TAG1(exc_sp->val_sp) && exc_sp->handler > ip) { - // Found a finally handler that isn't active. - // Getting here the stack looks like: - // (..., X, [iter0, iter1, ...,] ret_val) - // where X is pointed to by exc_sp->val_sp and in the case - // of a "with" block contains the context manager info. - // There may be 0 or more for-iterators between X and the - // return value, and these must be removed before control can - // pass to the finally code. We simply copy the ret_value down - // over these iterators, if they exist. If they don't then the - // following is a null operation. - mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp); - finally_sp[1] = sp[0]; - sp = &finally_sp[1]; - // We're going to run "finally" code as a coroutine - // (not calling it recursively). Set up a sentinel - // on a stack so it can return back to us when it is - // done (when WITH_CLEANUP or END_FINALLY reached). - PUSH(MP_OBJ_NEW_SMALL_INT(-1)); - ip = exc_sp->handler; - POP_EXC_BLOCK(); - goto dispatch_loop; + if (MP_TAGPTR_TAG1(exc_sp->val_sp)) { + if (exc_sp->handler > ip) { + // Found a finally handler that isn't active; run it. + // Getting here the stack looks like: + // (..., X, [iter0, iter1, ...,] ret_val) + // where X is pointed to by exc_sp->val_sp and in the case + // of a "with" block contains the context manager info. + // There may be 0 or more for-iterators between X and the + // return value, and these must be removed before control can + // pass to the finally code. We simply copy the ret_value down + // over these iterators, if they exist. If they don't then the + // following is a null operation. + mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp); + finally_sp[1] = sp[0]; + sp = &finally_sp[1]; + // We're going to run "finally" code as a coroutine + // (not calling it recursively). Set up a sentinel + // on a stack so it can return back to us when it is + // done (when WITH_CLEANUP or END_FINALLY reached). + PUSH(MP_OBJ_NEW_SMALL_INT(-1)); + ip = exc_sp->handler; + goto dispatch_loop; + } else { + // Found a finally handler that is already active; cancel it. + CANCEL_ACTIVE_FINALLY(sp); + } } POP_EXC_BLOCK(); } diff --git a/tests/basics/try_finally_break2.py b/tests/basics/try_finally_break2.py new file mode 100644 index 0000000000000..086e92e902f5b --- /dev/null +++ b/tests/basics/try_finally_break2.py @@ -0,0 +1,19 @@ +def foo(x): + for i in range(x): + for j in range(x): + try: + print(x, i, j, 1) + finally: + try: + try: + print(x, i, j, 2) + finally: + try: + 1 / 0 + finally: + print(x, i, j, 3) + break + finally: + print(x, i, j, 4) + break +print(foo(4)) diff --git a/tests/basics/try_finally_continue.py b/tests/basics/try_finally_continue.py new file mode 100644 index 0000000000000..50040e5de01ed --- /dev/null +++ b/tests/basics/try_finally_continue.py @@ -0,0 +1,17 @@ +def foo(x): + for i in range(x): + try: + pass + finally: + try: + try: + print(x, i) + finally: + try: + 1 / 0 + finally: + return 42 + finally: + print('continue') + continue +print(foo(4)) diff --git a/tests/basics/try_finally_continue.py.exp b/tests/basics/try_finally_continue.py.exp new file mode 100644 index 0000000000000..2901997b1aa18 --- /dev/null +++ b/tests/basics/try_finally_continue.py.exp @@ -0,0 +1,9 @@ +4 0 +continue +4 1 +continue +4 2 +continue +4 3 +continue +None diff --git a/tests/basics/try_finally_return5.py b/tests/basics/try_finally_return5.py new file mode 100644 index 0000000000000..aa2327e655563 --- /dev/null +++ b/tests/basics/try_finally_return5.py @@ -0,0 +1,17 @@ +def foo(x): + for i in range(x): + try: + pass + finally: + try: + try: + print(x, i) + finally: + try: + 1 / 0 + finally: + return 42 + finally: + print('return') + return 43 +print(foo(4)) From 809d89c794ceb44760ab997ff9a496488b4a2c0c Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 30 Sep 2019 16:06:20 +1000 Subject: [PATCH 0521/1299] py/runtime: Fix PEP479 behaviour throwing StopIteration into yield from. Commit 3f6ffe059f64b3ebc44dc0bbc63452cb8850702b implemented PEP479 but did not catch the case fixed in this commit. Found by coverage analysis, that the VM had uncovered code. --- py/runtime.c | 7 ++++++- py/vm.c | 11 ++--------- tests/basics/generator_pep479.py | 11 +++++++++++ tests/basics/generator_pep479.py.exp | 2 ++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/py/runtime.c b/py/runtime.c index 2657e7cc2588d..6b7a9ce3c6e1c 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1319,7 +1319,12 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th // will be propagated up. This behavior is approved by test_pep380.py // test_delegation_of_close_to_non_generator(), // test_delegating_throw_to_non_generator() - *ret_val = mp_make_raise_obj(throw_value); + if (mp_obj_exception_match(throw_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { + // PEP479: if StopIteration is raised inside a generator it is replaced with RuntimeError + *ret_val = mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator raised StopIteration"); + } else { + *ret_val = mp_make_raise_obj(throw_value); + } return MP_VM_RETURN_EXCEPTION; } } diff --git a/py/vm.c b/py/vm.c index 6e5015fc4310b..7c702f3863cfc 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1266,17 +1266,10 @@ unwind_jump:; DISPATCH(); } else { assert(ret_kind == MP_VM_RETURN_EXCEPTION); + assert(!EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))); // Pop exhausted gen sp--; - if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { - PUSH(mp_obj_exception_get_value(ret_value)); - // If we injected GeneratorExit downstream, then even - // if it was swallowed, we re-raise GeneratorExit - GENERATOR_EXIT_IF_NEEDED(t_exc); - DISPATCH(); - } else { - RAISE(ret_value); - } + RAISE(ret_value); } } diff --git a/tests/basics/generator_pep479.py b/tests/basics/generator_pep479.py index e422c349e7522..53853121702cb 100644 --- a/tests/basics/generator_pep479.py +++ b/tests/basics/generator_pep479.py @@ -27,3 +27,14 @@ def gen(): g.throw(StopIteration) except RuntimeError: print('RuntimeError') + +# throwing a StopIteration through yield from, will be converted to a RuntimeError +def gen(): + yield from range(2) + print('should not get here') +g = gen() +print(next(g)) +try: + g.throw(StopIteration) +except RuntimeError: + print('RuntimeError') diff --git a/tests/basics/generator_pep479.py.exp b/tests/basics/generator_pep479.py.exp index c64fe49561a98..610133946249a 100644 --- a/tests/basics/generator_pep479.py.exp +++ b/tests/basics/generator_pep479.py.exp @@ -3,3 +3,5 @@ RuntimeError StopIteration 1 RuntimeError +0 +RuntimeError From 27fe84e661d664c5c145b4b3a8d544dad7de0acb Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 4 Oct 2019 22:58:43 +1000 Subject: [PATCH 0522/1299] tests/basics: Add test for throw into yield-from with normal return. This test was found by missing coverage of a branch in py/nativeglue.c. --- tests/basics/gen_yield_from_throw.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/basics/gen_yield_from_throw.py b/tests/basics/gen_yield_from_throw.py index 804c53dda054b..1f76e13f3c34c 100644 --- a/tests/basics/gen_yield_from_throw.py +++ b/tests/basics/gen_yield_from_throw.py @@ -34,3 +34,17 @@ def gen2(): print(next(g)) except TypeError: print("got TypeError from downstream!") + +# thrown value is caught and then generator returns normally +def gen(): + try: + yield 123 + except ValueError: + print('ValueError') + # return normally after catching thrown exception +def gen2(): + yield from gen() + yield 789 +g = gen2() +print(next(g)) +print(g.throw(ValueError)) From 4107597b845c04b7184215b3202d596998141cb9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 13:35:19 +1000 Subject: [PATCH 0523/1299] py/emitnative: Add support for archs with windowed registers. Such that args/return regs for the parent are different to args/return regs for child calls. For an architecture to use this feature it should define the REG_PARENT_xxx macros before including py/emitnative.c. --- py/emitnative.c | 67 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/py/emitnative.c b/py/emitnative.c index 2c976606c717d..30f66f63345a0 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -94,6 +94,15 @@ #define OFFSETOF_OBJ_FUN_BC_GLOBALS (offsetof(mp_obj_fun_bc_t, globals) / sizeof(uintptr_t)) #define OFFSETOF_OBJ_FUN_BC_CONST_TABLE (offsetof(mp_obj_fun_bc_t, const_table) / sizeof(uintptr_t)) +// If not already defined, set parent args to same as child call registers +#ifndef REG_PARENT_RET +#define REG_PARENT_RET REG_RET +#define REG_PARENT_ARG_1 REG_ARG_1 +#define REG_PARENT_ARG_2 REG_ARG_2 +#define REG_PARENT_ARG_3 REG_ARG_3 +#define REG_PARENT_ARG_4 REG_ARG_4 +#endif + // Word index of nlr_buf_t.ret_val #define NLR_BUF_IDX_RET_VAL (1) @@ -413,16 +422,16 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs); #if N_X86 - asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1); + asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1); #endif // Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table - ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); + ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_3, 0); // Store function object (passed as first arg) to stack if needed if (NEED_FUN_OBJ(emit)) { - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_ARG_1); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1); } // Put n_args in REG_ARG_1, n_kw in REG_ARG_2, args array in REG_LOCAL_3 @@ -431,9 +440,9 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_2); asm_x86_mov_arg_to_r32(emit->as, 3, REG_LOCAL_3); #else - ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_ARG_2); - ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_ARG_3); - ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_4); + ASM_MOV_REG_REG(emit->as, REG_ARG_1, REG_PARENT_ARG_2); + ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_3); + ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_PARENT_ARG_4); #endif // Check number of args matches this function, and call mp_arg_check_num_sig if not @@ -482,14 +491,14 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 0, REG_GENERATOR_STATE); #else - ASM_MOV_REG_REG(emit->as, REG_GENERATOR_STATE, REG_ARG_1); + ASM_MOV_REG_REG(emit->as, REG_GENERATOR_STATE, REG_PARENT_ARG_1); #endif // Put throw value into LOCAL_IDX_EXC_VAL slot, for yield/yield-from #if N_X86 - asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2); + asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2); #endif - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_ARG_2); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_PARENT_ARG_2); // Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit)); @@ -505,22 +514,22 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // Prepare incoming arguments for call to mp_setup_code_state #if N_X86 - asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1); - asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2); - asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_3); - asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_4); + asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1); + asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2); + asm_x86_mov_arg_to_r32(emit->as, 2, REG_PARENT_ARG_3); + asm_x86_mov_arg_to_r32(emit->as, 3, REG_PARENT_ARG_4); #endif // Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table - ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); + ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CONST_TABLE); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_3, emit->scope->num_pos_args + emit->scope->num_kwonly_args); // Set code_state.fun_bc - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_ARG_1); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1); // Set code_state.ip (offset from start of this function to prelude info) // TODO this encoding may change size in the final pass, need to make it fixed - emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, emit->prelude_offset, REG_ARG_1); + emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, emit->prelude_offset, REG_PARENT_ARG_1); // Set code_state.n_state (only works on little endian targets due to n_state being uint16_t) emit_native_mov_state_imm_via(emit, emit->code_state_start + offsetof(mp_code_state_t, n_state) / sizeof(uintptr_t), emit->n_state, REG_ARG_1); @@ -528,6 +537,17 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // Put address of code_state into first arg ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, emit->code_state_start); + // Copy next 3 args if needed + #if REG_ARG_2 != REG_PARENT_ARG_2 + ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_PARENT_ARG_2); + #endif + #if REG_ARG_3 != REG_PARENT_ARG_3 + ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_PARENT_ARG_3); + #endif + #if REG_ARG_4 != REG_PARENT_ARG_4 + ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_PARENT_ARG_4); + #endif + // Call mp_setup_code_state to prepare code_state structure #if N_THUMB asm_thumb_bl_ind(emit->as, MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4); @@ -1174,7 +1194,7 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) { ASM_STORE_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, OFFSETOF_CODE_STATE_STATE); // Load return kind - ASM_MOV_REG_IMM(emit->as, REG_RET, MP_VM_RETURN_EXCEPTION); + ASM_MOV_REG_IMM(emit->as, REG_PARENT_RET, MP_VM_RETURN_EXCEPTION); ASM_EXIT(emit->as); } else { @@ -1229,7 +1249,7 @@ STATIC void emit_native_global_exc_exit(emit_t *emit) { } // Load return value - ASM_MOV_REG_LOCAL(emit->as, REG_RET, LOCAL_IDX_RET_VAL(emit)); + ASM_MOV_REG_LOCAL(emit->as, REG_PARENT_RET, LOCAL_IDX_RET_VAL(emit)); } ASM_EXIT(emit->as); @@ -2617,13 +2637,13 @@ STATIC void emit_native_return_value(emit_t *emit) { if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) { emit_pre_pop_discard(emit); if (return_vtype == VTYPE_PYOBJ) { - emit_native_mov_reg_const(emit, REG_RET, MP_F_CONST_NONE_OBJ); + emit_native_mov_reg_const(emit, REG_PARENT_RET, MP_F_CONST_NONE_OBJ); } else { ASM_MOV_REG_IMM(emit->as, REG_ARG_1, 0); } } else { vtype_kind_t vtype; - emit_pre_pop_reg(emit, &vtype, return_vtype == VTYPE_PYOBJ ? REG_RET : REG_ARG_1); + emit_pre_pop_reg(emit, &vtype, return_vtype == VTYPE_PYOBJ ? REG_PARENT_RET : REG_ARG_1); if (vtype != return_vtype) { EMIT_NATIVE_VIPER_TYPE_ERROR(emit, "return expected '%q' but got '%q'", @@ -2632,15 +2652,18 @@ STATIC void emit_native_return_value(emit_t *emit) { } if (return_vtype != VTYPE_PYOBJ) { emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, return_vtype, REG_ARG_2); + #if REG_RET != REG_PARENT_ARG_RET + ASM_MOV_REG_REG(emit->as, REG_PARENT_RET, REG_RET); + #endif } } else { vtype_kind_t vtype; - emit_pre_pop_reg(emit, &vtype, REG_RET); + emit_pre_pop_reg(emit, &vtype, REG_PARENT_RET); assert(vtype == VTYPE_PYOBJ); } if (NEED_GLOBAL_EXC_HANDLER(emit)) { // Save return value for the global exception handler to use - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_RET); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_RET_VAL(emit), REG_PARENT_RET); } emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); emit->last_emit_was_return_value = true; From 3504edc8048f8ab038ace50b0bbdf65b30619cc5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 13:44:22 +1000 Subject: [PATCH 0524/1299] py/emitnative: Add support for using setjmp with native emitter. To enable this feature the N_NLR_SETJMP macro should be set to 1 before including py/emitnative.c. --- py/emitnative.c | 14 ++++++++++++++ py/nativeglue.c | 9 +++++++++ py/runtime0.h | 1 + 3 files changed, 24 insertions(+) diff --git a/py/emitnative.c b/py/emitnative.c index 30f66f63345a0..22bfa2c78f0dc 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1154,6 +1154,10 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) { // Wrap everything in an nlr context ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 0); emit_call(emit, MP_F_NLR_PUSH); + #if N_NLR_SETJMP + ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 2); + emit_call(emit, MP_F_SETJMP); + #endif ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, start_label, true); } else { // Clear the unwind state @@ -1168,6 +1172,10 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) { ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_2, LOCAL_IDX_EXC_HANDLER_UNWIND(emit)); ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 0); emit_call(emit, MP_F_NLR_PUSH); + #if N_NLR_SETJMP + ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 2); + emit_call(emit, MP_F_SETJMP); + #endif ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_LOCAL_2); ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, global_except_label, true); @@ -1178,6 +1186,12 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) { // Global exception handler: check for valid exception handler emit_native_label_assign(emit, global_except_label); + #if N_NLR_SETJMP + // Reload REG_FUN_TABLE, since it may be clobbered by longjmp + emit_native_mov_reg_state(emit, REG_LOCAL_1, LOCAL_IDX_FUN_OBJ(emit)); + ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_1, REG_LOCAL_1, offsetof(mp_obj_fun_bc_t, const_table) / sizeof(uintptr_t)); + ASM_LOAD_REG_REG_OFFSET(emit->as, REG_FUN_TABLE, REG_LOCAL_1, emit->scope->num_pos_args + emit->scope->num_kwonly_args); + #endif ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_1, LOCAL_IDX_EXC_HANDLER_PC(emit)); ASM_JUMP_IF_REG_NONZERO(emit->as, REG_LOCAL_1, nlr_label, false); } diff --git a/py/nativeglue.c b/py/nativeglue.c index 62b76eb6b1052..4405b2d116be4 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -244,7 +244,11 @@ const void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_call_method_n_kw_var, mp_native_getiter, mp_native_iternext, + #if MICROPY_NLR_SETJMP + nlr_push_tail, + #else nlr_push, + #endif nlr_pop, mp_native_raise, mp_import_name, @@ -262,6 +266,11 @@ const void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_small_int_floor_divide, mp_small_int_modulo, mp_native_yield_from, + #if MICROPY_NLR_SETJMP + setjmp, + #else + NULL, + #endif }; #endif // MICROPY_EMIT_NATIVE diff --git a/py/runtime0.h b/py/runtime0.h index 1df6d0d5837fd..797ae00e60c75 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -201,6 +201,7 @@ typedef enum { MP_F_SMALL_INT_FLOOR_DIVIDE, MP_F_SMALL_INT_MODULO, MP_F_NATIVE_YIELD_FROM, + MP_F_SETJMP, MP_F_NUMBER_OF, } mp_fun_kind_t; From 306ec5369a1b82c2c9389cea1dfcb5bf1861c71a Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 13:47:24 +1000 Subject: [PATCH 0525/1299] py/emitnative: Add support for archs that cannot read executable data. In which case place the native function prelude in a bytes object, linked from the const_table of that function. An architecture should define N_PRELUDE_AS_BYTES_OBJ to 1 before including py/emitnative.c to emit correct machine code, then enable MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ so the runtime can correctly handle the prelude being in a bytes object. --- py/emitnative.c | 30 ++++++++++++++++++++++++++++++ py/objgenerator.c | 6 ++++++ 2 files changed, 36 insertions(+) diff --git a/py/emitnative.c b/py/emitnative.c index 22bfa2c78f0dc..f3bc8a5c489f9 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -48,6 +48,7 @@ #include "py/emit.h" #include "py/bc.h" +#include "py/objstr.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) @@ -92,6 +93,7 @@ #define OFFSETOF_CODE_STATE_IP (offsetof(mp_code_state_t, ip) / sizeof(uintptr_t)) #define OFFSETOF_CODE_STATE_SP (offsetof(mp_code_state_t, sp) / sizeof(uintptr_t)) #define OFFSETOF_OBJ_FUN_BC_GLOBALS (offsetof(mp_obj_fun_bc_t, globals) / sizeof(uintptr_t)) +#define OFFSETOF_OBJ_FUN_BC_BYTECODE (offsetof(mp_obj_fun_bc_t, bytecode) / sizeof(uintptr_t)) #define OFFSETOF_OBJ_FUN_BC_CONST_TABLE (offsetof(mp_obj_fun_bc_t, const_table) / sizeof(uintptr_t)) // If not already defined, set parent args to same as child call registers @@ -333,7 +335,11 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->pass = pass; emit->do_viper_types = scope->emit_options == MP_EMIT_OPT_VIPER; emit->stack_size = 0; + #if N_PRELUDE_AS_BYTES_OBJ + emit->const_table_cur_obj = emit->do_viper_types ? 0 : 1; // reserve first obj for prelude bytes obj + #else emit->const_table_cur_obj = 0; + #endif emit->const_table_cur_raw_code = 0; #if MICROPY_PERSISTENT_CODE_SAVE emit->qstr_link_cur = 0; @@ -483,7 +489,12 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { emit->code_state_start = 0; emit->stack_start = SIZEOF_CODE_STATE; + #if N_PRELUDE_AS_BYTES_OBJ + // Load index of prelude bytes object in const_table + mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)(emit->scope->num_pos_args + emit->scope->num_kwonly_args + 1)); + #else mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_offset); + #endif mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset); ASM_ENTRY(emit->as, SIZEOF_NLR_BUF); @@ -528,8 +539,17 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1); // Set code_state.ip (offset from start of this function to prelude info) + #if N_PRELUDE_AS_BYTES_OBJ + // Prelude is a bytes object in const_table; store ip = prelude->data - fun_bc->bytecode + ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, emit->scope->num_pos_args + emit->scope->num_kwonly_args + 1); + ASM_LOAD_REG_REG_OFFSET(emit->as, REG_LOCAL_3, REG_LOCAL_3, offsetof(mp_obj_str_t, data) / sizeof(uintptr_t)); + ASM_LOAD_REG_REG_OFFSET(emit->as, REG_PARENT_ARG_1, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_BYTECODE); + ASM_SUB_REG_REG(emit->as, REG_LOCAL_3, REG_PARENT_ARG_1); + emit_native_mov_state_reg(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, REG_LOCAL_3); + #else // TODO this encoding may change size in the final pass, need to make it fixed emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, emit->prelude_offset, REG_PARENT_ARG_1); + #endif // Set code_state.n_state (only works on little endian targets due to n_state being uint16_t) emit_native_mov_state_imm_via(emit, emit->code_state_start + offsetof(mp_code_state_t, n_state) / sizeof(uintptr_t), emit->n_state, REG_ARG_1); @@ -634,6 +654,16 @@ STATIC void emit_native_end_pass(emit_t *emit) { } } emit->n_cell = mp_asm_base_get_code_pos(&emit->as->base) - cell_start; + + #if N_PRELUDE_AS_BYTES_OBJ + // Prelude bytes object is after qstr arg names and mp_fun_table + size_t table_off = emit->scope->num_pos_args + emit->scope->num_kwonly_args + 1; + if (emit->pass == MP_PASS_EMIT) { + void *buf = emit->as->base.code_base + emit->prelude_offset; + size_t n = emit->as->base.code_offset - emit->prelude_offset; + emit->const_table[table_off] = (uintptr_t)mp_obj_new_bytes(buf, n); + } + #endif } ASM_END_PASS(emit->as); diff --git a/py/objgenerator.c b/py/objgenerator.c index 359dade88860c..2cfdb12f63853 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "py/bc.h" +#include "py/objstr.h" #include "py/objgenerator.h" #include "py/objfun.h" #include "py/stackctrl.h" @@ -88,6 +89,11 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k // Determine start of prelude, and extract n_state from it uintptr_t prelude_offset = ((uintptr_t*)self_fun->bytecode)[0]; + #if MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ + // Prelude is in bytes object in const_table, at index prelude_offset + mp_obj_str_t *prelude_bytes = MP_OBJ_TO_PTR(self_fun->const_table[prelude_offset]); + prelude_offset = (const byte*)prelude_bytes->data - self_fun->bytecode; + #endif const uint8_t *ip = self_fun->bytecode + prelude_offset; size_t n_state, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_args; MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_args); From f7ddc9416622493e6602dabf573b33b249756f8b Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 13:46:13 +1000 Subject: [PATCH 0526/1299] py/asmxtensa: Add support for Xtensa with windowed registers. Window-specific asm emit functions are added, along with a new macro option GENERIC_ASM_API_WIN. --- py/asmxtensa.c | 38 +++++++++++++++++++----- py/asmxtensa.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 105 insertions(+), 13 deletions(-) diff --git a/py/asmxtensa.c b/py/asmxtensa.c index a269e5e7fc0d1..22ea2300a290e 100644 --- a/py/asmxtensa.c +++ b/py/asmxtensa.c @@ -37,7 +37,6 @@ #define WORD_SIZE (4) #define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)) #define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)) -#define NUM_REGS_SAVED (5) void asm_xtensa_end_pass(asm_xtensa_t *as) { as->num_const = as->cur_const; @@ -69,7 +68,7 @@ void asm_xtensa_entry(asm_xtensa_t *as, int num_locals) { as->const_table = (uint32_t*)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); // adjust the stack-pointer to store a0, a12, a13, a14, a15 and locals, 16-byte aligned - as->stack_adjust = (((NUM_REGS_SAVED + num_locals) * WORD_SIZE) + 15) & ~15; + as->stack_adjust = (((ASM_XTENSA_NUM_REGS_SAVED + num_locals) * WORD_SIZE) + 15) & ~15; if (SIGNED_FIT8(-as->stack_adjust)) { asm_xtensa_op_addi(as, ASM_XTENSA_REG_A1, ASM_XTENSA_REG_A1, -as->stack_adjust); } else { @@ -79,14 +78,14 @@ void asm_xtensa_entry(asm_xtensa_t *as, int num_locals) { // save return value (a0) and callee-save registers (a12, a13, a14, a15) asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); - for (int i = 1; i < NUM_REGS_SAVED; ++i) { + for (int i = 1; i < ASM_XTENSA_NUM_REGS_SAVED; ++i) { asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i); } } void asm_xtensa_exit(asm_xtensa_t *as) { // restore registers - for (int i = NUM_REGS_SAVED - 1; i >= 1; --i) { + for (int i = ASM_XTENSA_NUM_REGS_SAVED - 1; i >= 1; --i) { asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A11 + i, ASM_XTENSA_REG_A1, i); } asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); @@ -102,6 +101,22 @@ void asm_xtensa_exit(asm_xtensa_t *as) { asm_xtensa_op_ret_n(as); } +void asm_xtensa_entry_win(asm_xtensa_t *as, int num_locals) { + // jump over the constants + asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4); + mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte + as->const_table = (uint32_t*)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); + + as->stack_adjust = 32 + ((((ASM_XTENSA_NUM_REGS_SAVED_WIN + num_locals) * WORD_SIZE) + 15) & ~15); + asm_xtensa_op_entry(as, ASM_XTENSA_REG_A1, as->stack_adjust); + asm_xtensa_op_s32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); +} + +void asm_xtensa_exit_win(asm_xtensa_t *as) { + asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A0, ASM_XTENSA_REG_A1, 0); + asm_xtensa_op_retw_n(as); +} + STATIC uint32_t get_label_dest(asm_xtensa_t *as, uint label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; @@ -178,15 +193,15 @@ void asm_xtensa_mov_reg_i32_optimised(asm_xtensa_t *as, uint reg_dest, uint32_t } void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src) { - asm_xtensa_op_s32i(as, reg_src, ASM_XTENSA_REG_A1, NUM_REGS_SAVED + local_num); + asm_xtensa_op_s32i(as, reg_src, ASM_XTENSA_REG_A1, local_num); } void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num) { - asm_xtensa_op_l32i(as, reg_dest, ASM_XTENSA_REG_A1, NUM_REGS_SAVED + local_num); + asm_xtensa_op_l32i(as, reg_dest, ASM_XTENSA_REG_A1, local_num); } void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num) { - uint off = (NUM_REGS_SAVED + local_num) * WORD_SIZE; + uint off = local_num * WORD_SIZE; if (SIGNED_FIT8(off)) { asm_xtensa_op_addi(as, reg_dest, ASM_XTENSA_REG_A1, off); } else { @@ -226,4 +241,13 @@ void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx) { asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0); } +void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) { + if (idx < 16) { + asm_xtensa_op_l32i_n(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx); + } else { + asm_xtensa_op_l32i(as, ASM_XTENSA_REG_A8, ASM_XTENSA_REG_FUN_TABLE_WIN, idx); + } + asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8); +} + #endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA diff --git a/py/asmxtensa.h b/py/asmxtensa.h index d95af14a5dabb..5eb40daf7887c 100644 --- a/py/asmxtensa.h +++ b/py/asmxtensa.h @@ -37,6 +37,16 @@ // callee save: a1, a12, a13, a14, a15 // caller save: a3 +// With windowed registers, size 8: +// - a0: return PC +// - a1: stack pointer, full descending, aligned to 16 bytes +// - a2-a7: incoming args, and essentially callee save +// - a2: return value +// - a8-a15: caller save temporaries +// - a10-a15: input args to called function +// - a10: return value of called function +// note: a0-a7 are saved automatically via window shift of called function + #define ASM_XTENSA_REG_A0 (0) #define ASM_XTENSA_REG_A1 (1) #define ASM_XTENSA_REG_A2 (2) @@ -96,6 +106,10 @@ #define ASM_XTENSA_ENCODE_RI7(op0, s, imm7) \ ((((imm7) & 0xf) << 12) | ((s) << 8) | ((imm7) & 0x70) | (op0)) +// Number of registers saved on the stack upon entry to function +#define ASM_XTENSA_NUM_REGS_SAVED (5) +#define ASM_XTENSA_NUM_REGS_SAVED_WIN (1) + typedef struct _asm_xtensa_t { mp_asm_base_t base; uint32_t cur_const; @@ -109,11 +123,18 @@ void asm_xtensa_end_pass(asm_xtensa_t *as); void asm_xtensa_entry(asm_xtensa_t *as, int num_locals); void asm_xtensa_exit(asm_xtensa_t *as); +void asm_xtensa_entry_win(asm_xtensa_t *as, int num_locals); +void asm_xtensa_exit_win(asm_xtensa_t *as); + void asm_xtensa_op16(asm_xtensa_t *as, uint16_t op); void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op); // raw instructions +static inline void asm_xtensa_op_entry(asm_xtensa_t *as, uint reg_src, int32_t num_bytes) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_BRI12(6, reg_src, 0, 3, (num_bytes / 8) & 0xfff)); +} + static inline void asm_xtensa_op_add_n(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(10, reg_dest, reg_src_a, reg_src_b)); } @@ -142,6 +163,10 @@ static inline void asm_xtensa_op_callx0(asm_xtensa_t *as, uint reg) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 3, 0)); } +static inline void asm_xtensa_op_callx8(asm_xtensa_t *as, uint reg) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALLX(0, 0, 0, 0, reg, 3, 2)); +} + static inline void asm_xtensa_op_j(asm_xtensa_t *as, int32_t rel18) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_CALL(6, 0, rel18 & 0x3ffff)); } @@ -194,6 +219,10 @@ static inline void asm_xtensa_op_ret_n(asm_xtensa_t *as) { asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(13, 15, 0, 0)); } +static inline void asm_xtensa_op_retw_n(asm_xtensa_t *as) { + asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RRRN(13, 15, 0, 1)); +} + static inline void asm_xtensa_op_s8i(asm_xtensa_t *as, uint reg_src, uint reg_base, uint byte_offset) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 4, reg_base, reg_src, byte_offset & 0xff)); } @@ -246,9 +275,11 @@ void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label); void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx); +void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); // Holds a pointer to mp_fun_table #define ASM_XTENSA_REG_FUN_TABLE ASM_XTENSA_REG_A15 +#define ASM_XTENSA_REG_FUN_TABLE_WIN ASM_XTENSA_REG_A7 #if GENERIC_ASM_API @@ -257,6 +288,9 @@ void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx); #define ASM_WORD_SIZE (4) +#if !GENERIC_ASM_API_WIN +// Configuration for non-windowed calls + #define REG_RET ASM_XTENSA_REG_A2 #define REG_ARG_1 ASM_XTENSA_REG_A2 #define REG_ARG_2 ASM_XTENSA_REG_A3 @@ -273,12 +307,47 @@ void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx); #define REG_LOCAL_3 ASM_XTENSA_REG_A14 #define REG_LOCAL_NUM (3) +#define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED #define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE +#define ASM_ENTRY(as, nlocal) asm_xtensa_entry((as), (nlocal)) +#define ASM_EXIT(as) asm_xtensa_exit((as)) +#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx)) + +#else +// Configuration for windowed calls with window size 8 + +#define REG_PARENT_RET ASM_XTENSA_REG_A2 +#define REG_PARENT_ARG_1 ASM_XTENSA_REG_A2 +#define REG_PARENT_ARG_2 ASM_XTENSA_REG_A3 +#define REG_PARENT_ARG_3 ASM_XTENSA_REG_A4 +#define REG_PARENT_ARG_4 ASM_XTENSA_REG_A5 +#define REG_RET ASM_XTENSA_REG_A10 +#define REG_ARG_1 ASM_XTENSA_REG_A10 +#define REG_ARG_2 ASM_XTENSA_REG_A11 +#define REG_ARG_3 ASM_XTENSA_REG_A12 +#define REG_ARG_4 ASM_XTENSA_REG_A13 + +#define REG_TEMP0 ASM_XTENSA_REG_A10 +#define REG_TEMP1 ASM_XTENSA_REG_A11 +#define REG_TEMP2 ASM_XTENSA_REG_A12 + +#define REG_LOCAL_1 ASM_XTENSA_REG_A4 +#define REG_LOCAL_2 ASM_XTENSA_REG_A5 +#define REG_LOCAL_3 ASM_XTENSA_REG_A6 +#define REG_LOCAL_NUM (3) + +#define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED_WIN +#define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE_WIN + +#define ASM_ENTRY(as, nlocal) asm_xtensa_entry_win((as), (nlocal)) +#define ASM_EXIT(as) asm_xtensa_exit_win((as)) +#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind_win((as), (idx)) + +#endif + #define ASM_T asm_xtensa_t #define ASM_END_PASS asm_xtensa_end_pass -#define ASM_ENTRY asm_xtensa_entry -#define ASM_EXIT asm_xtensa_exit #define ASM_JUMP asm_xtensa_j_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ @@ -288,15 +357,14 @@ void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx); #define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \ asm_xtensa_bcc_reg_reg_label(as, ASM_XTENSA_CC_EQ, reg1, reg2, label) #define ASM_JUMP_REG(as, reg) asm_xtensa_op_jx((as), (reg)) -#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx)) -#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_xtensa_mov_local_reg((as), (local_num), (reg_src)) +#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_xtensa_mov_local_reg((as), ASM_NUM_REGS_SAVED + (local_num), (reg_src)) #define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32_optimised((as), (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_U16(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm)) #define ASM_MOV_REG_IMM_FIX_WORD(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm)) -#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_xtensa_mov_reg_local((as), (reg_dest), (local_num)) +#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_xtensa_mov_reg_local((as), (reg_dest), ASM_NUM_REGS_SAVED + (local_num)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mov_n((as), (reg_dest), (reg_src)) -#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), (local_num)) +#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), ASM_NUM_REGS_SAVED + (local_num)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_xtensa_mov_reg_pcrel((as), (reg_dest), (label)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \ From 9adedce42e308692ea22a1e8e1154c51c1e8173d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Sep 2019 13:15:12 +1000 Subject: [PATCH 0527/1299] py: Add new Xtensa-Windowed arch for native emitter. Enabled via the configuration MICROPY_EMIT_XTENSAWIN. --- py/asmxtensa.c | 4 ++-- py/compile.c | 4 ++++ py/emit.h | 3 +++ py/emitnative.c | 4 ++-- py/emitnxtensawin.c | 23 +++++++++++++++++++++++ py/mpconfig.h | 10 +++++++++- py/nlr.h | 1 + py/persistentcode.c | 4 +++- py/persistentcode.h | 1 + py/py.mk | 1 + tools/mpy-tool.py | 1 + 11 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 py/emitnxtensawin.c diff --git a/py/asmxtensa.c b/py/asmxtensa.c index 22ea2300a290e..32e5e958a518c 100644 --- a/py/asmxtensa.c +++ b/py/asmxtensa.c @@ -30,7 +30,7 @@ #include "py/mpconfig.h" // wrapper around everything in this file -#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA +#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN #include "py/asmxtensa.h" @@ -250,4 +250,4 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) { asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8); } -#endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA +#endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN diff --git a/py/compile.c b/py/compile.c index 62b0f3938df7d..2c818a9340929 100644 --- a/py/compile.c +++ b/py/compile.c @@ -95,6 +95,7 @@ STATIC const emit_method_table_t *emit_native_table[] = { &emit_native_thumb_method_table, &emit_native_thumb_method_table, &emit_native_xtensa_method_table, + &emit_native_xtensawin_method_table, }; #elif MICROPY_EMIT_NATIVE @@ -109,6 +110,8 @@ STATIC const emit_method_table_t *emit_native_table[] = { #define NATIVE_EMITTER(f) emit_native_arm_##f #elif MICROPY_EMIT_XTENSA #define NATIVE_EMITTER(f) emit_native_xtensa_##f +#elif MICROPY_EMIT_XTENSAWIN +#define NATIVE_EMITTER(f) emit_native_xtensawin_##f #else #error "unknown native emitter" #endif @@ -131,6 +134,7 @@ STATIC const emit_inline_asm_method_table_t *emit_asm_table[] = { &emit_inline_thumb_method_table, &emit_inline_thumb_method_table, &emit_inline_xtensa_method_table, + NULL, }; #elif MICROPY_EMIT_INLINE_ASM diff --git a/py/emit.h b/py/emit.h index b3b6d755bfa09..26d027a7abda0 100644 --- a/py/emit.h +++ b/py/emit.h @@ -174,6 +174,7 @@ extern const emit_method_table_t emit_native_x86_method_table; extern const emit_method_table_t emit_native_thumb_method_table; extern const emit_method_table_t emit_native_arm_method_table; extern const emit_method_table_t emit_native_xtensa_method_table; +extern const emit_method_table_t emit_native_xtensawin_method_table; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops; @@ -185,6 +186,7 @@ emit_t *emit_native_x86_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t ma emit_t *emit_native_thumb_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_arm_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_xtensa_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); +emit_t *emit_native_xtensawin_new(mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); void emit_bc_set_max_num_labels(emit_t* emit, mp_uint_t max_num_labels); @@ -194,6 +196,7 @@ void emit_native_x86_free(emit_t *emit); void emit_native_thumb_free(emit_t *emit); void emit_native_arm_free(emit_t *emit); void emit_native_xtensa_free(emit_t *emit); +void emit_native_xtensawin_free(emit_t *emit); void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope); void mp_emit_bc_end_pass(emit_t *emit); diff --git a/py/emitnative.c b/py/emitnative.c index f3bc8a5c489f9..e038b87785d9a 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -58,7 +58,7 @@ #endif // wrapper around everything in this file -#if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA +#if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA || N_XTENSAWIN // C stack layout for native functions: // 0: nlr_buf_t [optional] @@ -2404,7 +2404,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { ASM_ARM_CC_NE, }; asm_arm_setcc_reg(emit->as, REG_RET, ccs[op - MP_BINARY_OP_LESS]); - #elif N_XTENSA + #elif N_XTENSA || N_XTENSAWIN static uint8_t ccs[6] = { ASM_XTENSA_CC_LT, 0x80 | ASM_XTENSA_CC_LT, // for GT we'll swap args diff --git a/py/emitnxtensawin.c b/py/emitnxtensawin.c new file mode 100644 index 0000000000000..38d5db13ea450 --- /dev/null +++ b/py/emitnxtensawin.c @@ -0,0 +1,23 @@ +// Xtensa-Windowed specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_XTENSAWIN + +// this is defined so that the assembler exports generic assembler API macros +#define GENERIC_ASM_API (1) +#define GENERIC_ASM_API_WIN (1) +#include "py/asmxtensa.h" + +// Word indices of REG_LOCAL_x in nlr_buf_t +#define NLR_BUF_IDX_LOCAL_1 (2 + 4) // a4 +#define NLR_BUF_IDX_LOCAL_2 (2 + 5) // a5 +#define NLR_BUF_IDX_LOCAL_3 (2 + 6) // a6 + +#define N_NLR_SETJMP (1) +#define N_PRELUDE_AS_BYTES_OBJ (1) +#define N_XTENSAWIN (1) +#define EXPORT_FUN(name) emit_native_xtensawin_##name +#include "py/emitnative.c" + +#endif diff --git a/py/mpconfig.h b/py/mpconfig.h index 64dadde92d0c7..4172b5fcfeb6c 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -323,8 +323,16 @@ #define MICROPY_EMIT_INLINE_XTENSA (0) #endif +// Whether to emit Xtensa-Windowed native code +#ifndef MICROPY_EMIT_XTENSAWIN +#define MICROPY_EMIT_XTENSAWIN (0) +#endif + // Convenience definition for whether any native emitter is enabled -#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA) +#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN) + +// Select prelude-as-bytes-object for certain emitters +#define MICROPY_EMIT_NATIVE_PRELUDE_AS_BYTES_OBJ (MICROPY_EMIT_XTENSAWIN) // Convenience definition for whether any inline assembler emitter is enabled #define MICROPY_EMIT_INLINE_ASM (MICROPY_EMIT_INLINE_THUMB || MICROPY_EMIT_INLINE_XTENSA) diff --git a/py/nlr.h b/py/nlr.h index 3e4b31d92be89..f2453bc46008d 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -40,6 +40,7 @@ #define MICROPY_NLR_NUM_REGS_ARM_THUMB (10) #define MICROPY_NLR_NUM_REGS_ARM_THUMB_FP (10 + 6) #define MICROPY_NLR_NUM_REGS_XTENSA (10) +#define MICROPY_NLR_NUM_REGS_XTENSAWIN (17) // If MICROPY_NLR_SETJMP is not enabled then auto-detect the machine arch #if !MICROPY_NLR_SETJMP diff --git a/py/persistentcode.c b/py/persistentcode.c index 2109d937989c9..6a8a866ac5cbd 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -71,6 +71,8 @@ #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV6) #elif MICROPY_EMIT_XTENSA #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSA) +#elif MICROPY_EMIT_XTENSAWIN +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSAWIN) #else #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) #endif @@ -196,7 +198,7 @@ STATIC void arch_link_qstr(uint8_t *pc, bool is_obj, qstr qst) { if (is_obj) { val = (mp_uint_t)MP_OBJ_NEW_QSTR(qst); } - #if MICROPY_EMIT_X86 || MICROPY_EMIT_X64 || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA + #if MICROPY_EMIT_X86 || MICROPY_EMIT_X64 || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN pc[0] = val & 0xff; pc[1] = (val >> 8) & 0xff; pc[2] = (val >> 16) & 0xff; diff --git a/py/persistentcode.h b/py/persistentcode.h index 67c5f3463d66a..aba44ea2db1cb 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -44,6 +44,7 @@ enum { MP_NATIVE_ARCH_ARMV7EMSP, MP_NATIVE_ARCH_ARMV7EMDP, MP_NATIVE_ARCH_XTENSA, + MP_NATIVE_ARCH_XTENSAWIN, }; mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader); diff --git a/py/py.mk b/py/py.mk index d97852dd431b7..5669e33fccfc4 100644 --- a/py/py.mk +++ b/py/py.mk @@ -76,6 +76,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ asmxtensa.o \ emitnxtensa.o \ emitinlinextensa.o \ + emitnxtensawin.o \ formatfloat.o \ parsenumbase.o \ parsenum.o \ diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 8c0f5db18a931..ab783f4184586 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -102,6 +102,7 @@ def access(self, idx): MP_NATIVE_ARCH_ARMV7EMSP = 7 MP_NATIVE_ARCH_ARMV7EMDP = 8 MP_NATIVE_ARCH_XTENSA = 9 +MP_NATIVE_ARCH_XTENSAWIN = 10 MP_BC_MASK_EXTRA_BYTE = 0x9e From 917f027c0b4bbb8170fdf529b4d4c1b2e1e5a931 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 13:47:44 +1000 Subject: [PATCH 0528/1299] esp32: Enable native emitter. --- ports/esp32/main.c | 10 ++++++++++ ports/esp32/mpconfigport.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/ports/esp32/main.c b/ports/esp32/main.c index 7106e0bf5e4e1..b0d1b1537065d 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -172,3 +172,13 @@ void nlr_jump_fail(void *val) { void mbedtls_debug_set_threshold(int threshold) { (void)threshold; } + +void *esp_native_code_commit(void *buf, size_t len) { + len = (len + 3) & ~3; + uint32_t *p = heap_caps_malloc(len, MALLOC_CAP_EXEC); + if (p == NULL) { + m_malloc_fail(len); + } + memcpy(p, buf, len); + return p; +} diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 1c0d8700facda..63657741ce45f 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -20,6 +20,9 @@ // emitters #define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_EMIT_XTENSAWIN (1) +void *esp_native_code_commit(void*, size_t); +#define MP_PLAT_COMMIT_EXEC(buf, len) esp_native_code_commit(buf, len) // compiler configuration #define MICROPY_COMP_MODULE_CONST (1) From 1d21b4e7d17fe22dc046a1bfd3251d25c013bd05 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Sep 2019 13:16:00 +1000 Subject: [PATCH 0529/1299] mpy-cross: Enable Xtensa-Windowed native emitter. Selectable via the command line: -march=xtensawin. --- mpy-cross/main.c | 5 ++++- mpy-cross/mpconfigport.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mpy-cross/main.c b/mpy-cross/main.c index be43598c5fafa..4a4fccb3b745f 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -109,7 +109,7 @@ STATIC int usage(char **argv) { "-msmall-int-bits=number : set the maximum bits used to encode a small-int\n" "-mno-unicode : don't support unicode in compiled strings\n" "-mcache-lookup-bc : cache map lookups in the bytecode\n" -"-march= : set architecture for native emitter; x86, x64, armv6, armv7m, xtensa\n" +"-march= : set architecture for native emitter; x86, x64, armv6, armv7m, xtensa, xtensawin\n" "\n" "Implementation specific options:\n", argv[0] ); @@ -288,6 +288,9 @@ MP_NOINLINE int main_(int argc, char **argv) { } else if (strcmp(arch, "xtensa") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSA; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSA; + } else if (strcmp(arch, "xtensawin") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSAWIN; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSAWIN; } else { return usage(argv); } diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index 314526928011a..533f58aabe89b 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -39,6 +39,7 @@ #define MICROPY_EMIT_ARM (1) #define MICROPY_EMIT_XTENSA (1) #define MICROPY_EMIT_INLINE_XTENSA (1) +#define MICROPY_EMIT_XTENSAWIN (1) #define MICROPY_DYNAMIC_COMPILER (1) #define MICROPY_COMP_CONST_FOLDING (1) From deef6f3718bb3166eadb78f2fe32d139e4a7803e Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 1 Oct 2019 12:51:57 +1000 Subject: [PATCH 0530/1299] travis: Build unix nanbox with PYTHON=python2. To test build support with Python 2.7. --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index a72f3bc1a3192..617cc2035ef35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -94,16 +94,16 @@ jobs: - make ${MAKEOPTS} -C ports/unix test - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython ./run-perfbench.py 1000 1000) - # unix nanbox + # unix nanbox (and using Python 2 to check it can run the build scripts) - stage: test env: NAME="unix nanbox port build and tests" install: - sudo apt-get install gcc-multilib libffi-dev:i386 script: - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - - make ${MAKEOPTS} -C mpy-cross - - make ${MAKEOPTS} -C ports/unix deplibs - - make ${MAKEOPTS} -C ports/unix nanbox + - make ${MAKEOPTS} -C mpy-cross PYTHON=python2 + - make ${MAKEOPTS} -C ports/unix PYTHON=python2 deplibs + - make ${MAKEOPTS} -C ports/unix PYTHON=python2 nanbox - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_nanbox ./run-tests) # unix stackless From a0ce01f62e4e5f8103ab3e607f90fe931e866892 Mon Sep 17 00:00:00 2001 From: Martin Fischer Date: Thu, 3 Oct 2019 22:30:20 +0200 Subject: [PATCH 0531/1299] stm32/usbdev: Fix compile error if MICROPY_HW_USB_CDC_NUM is set to 2. Fixes regression introduced by 6705767da1f7dba7a04e1d16c380a650f1f1074f --- ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 0b9407654320d..5e24730a0fac9 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -556,7 +556,6 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC2_MSC, HID_IN_EP_WITH_CDC2_MSC, HID_OUT_EP_WITH_CDC2_MSC); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; - usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; usbd->hid->in_ep = HID_IN_EP_WITH_CDC2_MSC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC2_MSC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC2_MSC; From 4a6974bea598a9b76c4a49afcc0d6f82760a7006 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 5 Oct 2019 23:51:33 +1000 Subject: [PATCH 0532/1299] stm32/boards/PYBD_SF2: Put nimble library in external QSPI XIP flash. The BLE stack is not performance critical, so put it in external memory-mapped flash to save internal flash for other things (like frozen bytecode). --- ports/stm32/boards/PYBD_SF2/f722_qspi.ld | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld index 554d34b4926f9..b55bfe95fb71c 100644 --- a/ports/stm32/boards/PYBD_SF2/f722_qspi.ld +++ b/ports/stm32/boards/PYBD_SF2/f722_qspi.ld @@ -49,6 +49,7 @@ SECTIONS { . = ALIGN(4); *lib/mbedtls/*(.text* .rodata*) + *lib/mynewt-nimble/*(.text* .rodata*) . = ALIGN(512); *(.big_const*) . = ALIGN(4); From 902bb4ceae6ca3a8379df35f12ccffc0b492d950 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 1 Oct 2019 23:46:53 +1000 Subject: [PATCH 0533/1299] stm32: Extract port-specific Nimble implementation. On other ports (e.g. ESP32) they provide a complete Nimble implementation (i.e. we don't need to use the code in extmod/nimble). This change extracts out the bits that we don't need to use in other ports: - malloc/free/realloc for Nimble memory. - pendsv poll handler - depowering the cywbt Also cleans up the root pointer management. --- extmod/modbluetooth_nimble.c | 214 +++++++++------------------------- extmod/modbluetooth_nimble.h | 54 +++++++++ extmod/nimble/nimble/npl_os.c | 80 +++++++++++++ ports/stm32/Makefile | 1 + ports/stm32/mpconfigport.h | 3 +- ports/stm32/nimble.c | 82 +++++++++++++ 6 files changed, 274 insertions(+), 160 deletions(-) create mode 100644 extmod/modbluetooth_nimble.h create mode 100644 ports/stm32/nimble.c diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 959360cee7545..1e7211bfe8f1c 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -28,25 +28,22 @@ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" -#include "systick.h" -#include "pendsv.h" #if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE -#ifndef MICROPY_PY_BLUETOOTH_DEFAULT_NAME -#define MICROPY_PY_BLUETOOTH_DEFAULT_NAME "PYBD" -#endif - -#include "extmod/modbluetooth.h" +#include "modbluetooth_nimble.h" +#include "modbluetooth.h" #include "host/ble_hs.h" #include "host/util/util.h" #include "nimble/ble.h" #include "nimble/nimble_port.h" #include "services/gap/ble_svc_gap.h" -#include "transport/uart/ble_hci_uart.h" -#define DEBUG_MALLOC_printf(...) //printf(__VA_ARGS__) +#ifndef MICROPY_PY_BLUETOOTH_DEFAULT_NAME +#define MICROPY_PY_BLUETOOTH_DEFAULT_NAME "PYBD" +#endif + #define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__) STATIC int8_t ble_hs_err_to_errno_table[] = { @@ -90,82 +87,6 @@ STATIC int ble_hs_err_to_errno(int err) { } } -// Maintain a linked list of heap memory that we've passed to Nimble, -// discoverable via the bluetooth_nimble_memory root pointer. - -// MP_STATE_PORT(bluetooth_nimble_memory) is a pointer to [next, prev, data...]. - -// TODO: This is duplicated from mbedtls. Perhaps make this a generic feature? -void *m_malloc_bluetooth(size_t size) { - void **ptr = m_malloc0(size + 2 * sizeof(uintptr_t)); - if (MP_STATE_PORT(bluetooth_nimble_memory) != NULL) { - MP_STATE_PORT(bluetooth_nimble_memory)[0] = ptr; - } - ptr[0] = NULL; - ptr[1] = MP_STATE_PORT(bluetooth_nimble_memory); - MP_STATE_PORT(bluetooth_nimble_memory) = ptr; - return &ptr[2]; -} - -#define m_new_bluetooth(type, num) ((type*)m_malloc_bluetooth(sizeof(type) * (num))) - -void m_free_bluetooth(void *ptr_in) { - void **ptr = &((void**)ptr_in)[-2]; - if (ptr[1] != NULL) { - ((void**)ptr[1])[0] = ptr[0]; - } - if (ptr[0] != NULL) { - ((void**)ptr[0])[1] = ptr[1]; - } else { - MP_STATE_PORT(bluetooth_nimble_memory) = ptr[1]; - } - m_free(ptr); -} - -// Check if a nimble ptr is tracked. -// If it isn't, that means that it's from a previous soft-reset cycle. -STATIC bool is_valid_nimble_malloc(void *ptr) { - DEBUG_MALLOC_printf("NIMBLE is_valid_nimble_malloc(%p)\n", ptr); - void** search = MP_STATE_PORT(bluetooth_nimble_memory); - while (search) { - if (&search[2] == ptr) { - return true; - } - - search = (void**)search[1]; - } - return false; -} - -void *nimble_malloc(size_t size) { - DEBUG_MALLOC_printf("NIMBLE malloc(%u)\n", (uint)size); - void* ptr = m_malloc_bluetooth(size); - DEBUG_MALLOC_printf(" --> %p\n", ptr); - return ptr; -} - -// Only free if it's still a valid pointer. -void nimble_free(void *ptr) { - DEBUG_MALLOC_printf("NIMBLE free(%p)\n", ptr); - if (ptr && is_valid_nimble_malloc(ptr)) { - m_free_bluetooth(ptr); - } -} - -// Only realloc if it's still a valid pointer. Otherwise just malloc. -void *nimble_realloc(void *ptr, size_t size) { - // This is only used by ble_gatts.c to grow the queue of pending services to be registered. - DEBUG_MALLOC_printf("NIMBLE realloc(%p, %u)\n", ptr, (uint)size); - void *ptr2 = nimble_malloc(size); - if (ptr && is_valid_nimble_malloc(ptr)) { - // If it's a realloc and we still have the old data, then copy it. - // This will happen as we add services. - memcpy(ptr2, ptr, size); - m_free_bluetooth(ptr); - } - return ptr2; -} - STATIC ble_uuid_t* create_nimble_uuid(const mp_obj_bluetooth_uuid_t *uuid) { if (uuid->type == MP_BLUETOOTH_UUID_TYPE_16) { ble_uuid16_t *result = m_new(ble_uuid16_t, 1); @@ -227,50 +148,13 @@ STATIC ble_addr_t create_nimble_addr(uint8_t addr_type, const uint8_t *addr) { #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE -STATIC mp_map_t *gatts_db = MP_OBJ_NULL; - typedef struct { uint8_t *data; size_t data_alloc; size_t data_len; } gatts_db_entry_t; -/******************************************************************************/ -// RUN LOOP - -enum { - BLE_STATE_OFF, - BLE_STATE_STARTING, - BLE_STATE_ACTIVE, -}; - -static volatile int ble_state = BLE_STATE_OFF; - -extern void nimble_uart_process(void); -extern void os_eventq_run_all(void); -extern void os_callout_process(void); - -// Hook for pendsv poller to run this periodically every 128ms -#define NIMBLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0) - -void nimble_poll(void) { - if (ble_state == BLE_STATE_OFF) { - return; - } - - nimble_uart_process(); - os_callout_process(); - os_eventq_run_all(); -} - -void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms) { - if (NIMBLE_TICK(ticks_ms)) { - pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll); - } -} - -/******************************************************************************/ -// BINDINGS +volatile int mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF; STATIC void reset_cb(int reason) { (void)reason; @@ -308,11 +192,11 @@ STATIC void sync_cb(void) { ble_svc_gap_device_name_set(MICROPY_PY_BLUETOOTH_DEFAULT_NAME); - ble_state = BLE_STATE_ACTIVE; + mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE; } STATIC void create_gatts_db_entry(uint16_t handle) { - mp_map_elem_t *elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(handle), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(handle), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); gatts_db_entry_t *entry = m_new(gatts_db_entry_t, 1); entry->data = m_new(uint8_t, MP_BLUETOOTH_MAX_ATTR_SIZE); entry->data_alloc = MP_BLUETOOTH_MAX_ATTR_SIZE; @@ -390,27 +274,27 @@ int mp_bluetooth_init(void) { // Clean up if necessary. mp_bluetooth_deinit(); - MP_STATE_PORT(bluetooth_nimble_memory) = NULL; - ble_hs_cfg.reset_cb = reset_cb; ble_hs_cfg.sync_cb = sync_cb; ble_hs_cfg.gatts_register_cb = gatts_register_cb; ble_hs_cfg.store_status_cb = ble_store_util_status_rr; - gatts_db = m_new_bluetooth(mp_map_t, 1); + MP_STATE_PORT(bluetooth_nimble_root_pointers) = m_new0(mp_bluetooth_nimble_root_pointers_t, 1); + MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db = m_new(mp_map_t, 1); + + mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_STARTING; - ble_hci_uart_init(); + mp_bluetooth_nimble_port_preinit(); nimble_port_init(); + mp_bluetooth_nimble_port_postinit(); // By default, just register the default gap service. ble_svc_gap_init(); - ble_state = BLE_STATE_STARTING; - - ble_hs_start(); + mp_bluetooth_nimble_port_start(); // Wait for sync callback - while (ble_state != BLE_STATE_ACTIVE) { + while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE) { MICROPY_EVENT_POLL_HOOK } @@ -419,13 +303,13 @@ int mp_bluetooth_init(void) { // Called when the host stop procedure has completed. STATIC void ble_hs_shutdown_stop_cb(int status, void *arg) { - ble_state = BLE_STATE_OFF; + mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF; } STATIC struct ble_hs_stop_listener ble_hs_shutdown_stop_listener; void mp_bluetooth_deinit(void) { - if (ble_state == BLE_STATE_OFF) { + if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { return; } @@ -434,25 +318,27 @@ void mp_bluetooth_deinit(void) { mp_bluetooth_gap_scan_stop(); #endif - ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, - NULL); + ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, NULL); - while (ble_state != BLE_STATE_OFF) { + while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { MICROPY_EVENT_POLL_HOOK } - // TODO: This should be a port-specific hook. - #ifdef pyb_pin_BT_REG_ON - mp_hal_pin_low(pyb_pin_BT_REG_ON); - #endif + mp_bluetooth_nimble_port_deinit(); + + MP_STATE_PORT(bluetooth_nimble_root_pointers) = NULL; } bool mp_bluetooth_is_enabled(void) { - return ble_state == BLE_STATE_ACTIVE; + return mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE; } void mp_bluetooth_get_device_addr(uint8_t *addr) { + #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR + ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr, NULL); + #else mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr); + #endif } int mp_bluetooth_gap_advertise_start(bool connectable, uint16_t interval_ms, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) { @@ -528,7 +414,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, } #endif - elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return BLE_ATT_ERR_ATTR_NOT_FOUND; } @@ -539,7 +425,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, return 0; case BLE_GATT_ACCESS_OP_WRITE_CHR: case BLE_GATT_ACCESS_OP_WRITE_DSC: - elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return BLE_ATT_ERR_ATTR_NOT_FOUND; } @@ -561,11 +447,13 @@ int mp_bluetooth_gatts_register_service_begin(bool reset) { } // Reset the gatt characteristic value db. - mp_map_init(gatts_db, 0); + mp_map_init(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, 0); // By default, just register the default gap service. ble_svc_gap_init(); + MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services = 0; + return 0; } @@ -575,16 +463,22 @@ int mp_bluetooth_gatts_register_service_end() { return ble_hs_err_to_errno(ret); } + for (int i = 0; i < MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services; ++i) { + MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[i] = NULL; + } + MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services = 0; + return 0; } int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) { - // TODO: These allocs need to last until mp_bluetooth_gatts_register_service_end. - // Using m_new_bluetooth means they get leaked, but m_new would mean that they wouldn't be findable by GC. + if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services == MP_BLUETOOTH_NIMBLE_MAX_SERVICES) { + return MP_E2BIG; + } size_t handle_index = 0; size_t descriptor_index = 0; - struct ble_gatt_chr_def *characteristics = m_new_bluetooth(struct ble_gatt_chr_def, num_characteristics + 1); + struct ble_gatt_chr_def *characteristics = m_new(struct ble_gatt_chr_def, num_characteristics + 1); for (size_t i = 0; i < num_characteristics; ++i) { characteristics[i].uuid = create_nimble_uuid(characteristic_uuids[i]); characteristics[i].access_cb = characteristic_access_cb; @@ -597,7 +491,7 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m if (num_descriptors[i] == 0) { characteristics[i].descriptors = NULL; } else { - struct ble_gatt_dsc_def *descriptors = m_new_bluetooth(struct ble_gatt_dsc_def, num_descriptors[i] + 1); + struct ble_gatt_dsc_def *descriptors = m_new(struct ble_gatt_dsc_def, num_descriptors[i] + 1); for (size_t j = 0; j < num_descriptors[i]; ++j) { descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index]); @@ -616,13 +510,15 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m } characteristics[num_characteristics].uuid = NULL; // no more characteristics - struct ble_gatt_svc_def *service = m_new_bluetooth(struct ble_gatt_svc_def, 2); + struct ble_gatt_svc_def *service = m_new(struct ble_gatt_svc_def, 2); service[0].type = BLE_GATT_SVC_TYPE_PRIMARY; service[0].uuid = create_nimble_uuid(service_uuid); service[0].includes = NULL; service[0].characteristics = characteristics; service[1].type = 0; // no more services + MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services++] = service; + // Note: advertising must be stopped for gatts registration to work int ret = ble_gatts_count_cfg(service); @@ -643,7 +539,7 @@ int mp_bluetooth_gap_disconnect(uint16_t conn_handle) { } int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) { - mp_map_elem_t *elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return MP_EINVAL; } @@ -654,7 +550,7 @@ int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *valu } int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len) { - mp_map_elem_t *elem = mp_map_lookup(gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); if (!elem) { return MP_EINVAL; } @@ -693,7 +589,7 @@ int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { - DEBUG_EVENT_printf("gap_scan_cb: event=%d\n", event->type); + DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->disc ? event->disc.event_type : -1); if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) { mp_bluetooth_gap_on_scan_complete(); @@ -704,9 +600,6 @@ STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { return 0; } - DEBUG_EVENT_printf(" --> type %d\n", event->disc.event_type); - - if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND) { bool connectable = event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND; uint8_t addr[6]; @@ -821,8 +714,7 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, } STATIC int peripheral_discover_service_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) { - DEBUG_EVENT_printf("peripheral_discover_service_cb: conn_handle=%d status=%d start_handle=%d\n", conn_handle, error->status, service->start_handle); - // TODO: Find out what error->status == 14 means (probably "end of services"). + DEBUG_EVENT_printf("peripheral_discover_service_cb: conn_handle=%d status=%d start_handle=%d\n", conn_handle, error->status, service ? service->start_handle : -1); if (error->status == 0) { mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(&service->uuid); mp_bluetooth_gattc_on_primary_service_result(conn_handle, service->start_handle, service->end_handle, &service_uuid); @@ -836,6 +728,7 @@ int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle) { } STATIC int ble_gatt_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) { + DEBUG_EVENT_printf("ble_gatt_characteristic_cb: conn_handle=%d status=%d def_handle=%d val_handle=%d\n", conn_handle, error->status, characteristic ? characteristic->def_handle : -1, characteristic ? characteristic->val_handle : -1); if (error->status == 0) { mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid); mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid); @@ -849,6 +742,7 @@ int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t s } STATIC int ble_gatt_descriptor_cb(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t characteristic_val_handle, const struct ble_gatt_dsc *descriptor, void *arg) { + DEBUG_EVENT_printf("ble_gatt_descriptor_cb: conn_handle=%d status=%d chr_handle=%d dsc_handle=%d\n", conn_handle, error->status, characteristic_val_handle, descriptor ? descriptor->handle : -1); if (error->status == 0) { mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(&descriptor->uuid); mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor->handle, &descriptor_uuid); @@ -862,6 +756,7 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start } STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { + DEBUG_EVENT_printf("ble_gatt_attr_read_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); // TODO: Maybe send NULL if error->status non-zero. if (error->status == 0) { uint8_t buf[MP_BLUETOOTH_MAX_ATTR_SIZE]; @@ -879,6 +774,7 @@ int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) { } STATIC int ble_gatt_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { + DEBUG_EVENT_printf("ble_gatt_attr_write_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); mp_bluetooth_gattc_on_write_status(conn_handle, attr->handle, error->status); return 0; } diff --git a/extmod/modbluetooth_nimble.h b/extmod/modbluetooth_nimble.h new file mode 100644 index 0000000000000..e2474a6ee50b9 --- /dev/null +++ b/extmod/modbluetooth_nimble.h @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_NIMBLE_H +#define MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_NIMBLE_H + +#define MP_BLUETOOTH_NIMBLE_MAX_SERVICES (8) + +typedef struct _mp_bluetooth_nimble_root_pointers_t { + // Characteristic (and descriptor) value storage. + mp_map_t *gatts_db; + + // Pending service definitions. + size_t n_services; + struct ble_gatt_svc_def *services[MP_BLUETOOTH_NIMBLE_MAX_SERVICES]; +} mp_bluetooth_nimble_root_pointers_t; + +enum { + MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF, + MP_BLUETOOTH_NIMBLE_BLE_STATE_STARTING, + MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE, +}; + +extern volatile int mp_bluetooth_nimble_ble_state; + +void mp_bluetooth_nimble_port_preinit(void); +void mp_bluetooth_nimble_port_postinit(void); +void mp_bluetooth_nimble_port_deinit(void); +void mp_bluetooth_nimble_port_start(void); + +#endif // MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_NIMBLE_H diff --git a/extmod/nimble/nimble/npl_os.c b/extmod/nimble/nimble/npl_os.c index 0f852c8780224..4875d2d1ad45c 100644 --- a/extmod/nimble/nimble/npl_os.c +++ b/extmod/nimble/nimble/npl_os.c @@ -26,9 +26,12 @@ #include #include "py/mphal.h" +#include "py/runtime.h" +#include "nimble/ble.h" #include "nimble/nimble_npl.h" #define DEBUG_OS_printf(...) //printf(__VA_ARGS__) +#define DEBUG_MALLOC_printf(...) //printf(__VA_ARGS__) #define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__) #define DEBUG_MUTEX_printf(...) //printf(__VA_ARGS__) #define DEBUG_SEM_printf(...) //printf(__VA_ARGS__) @@ -46,6 +49,83 @@ void *ble_npl_get_current_task_id(void) { return NULL; } +/******************************************************************************/ +// malloc + +// Maintain a linked list of heap memory that we've passed to Nimble, +// discoverable via the bluetooth_nimble_memory root pointer. + +// MP_STATE_PORT(bluetooth_nimble_memory) is a pointer to [next, prev, data...]. + +// TODO: This is duplicated from mbedtls. Perhaps make this a generic feature? +void *m_malloc_bluetooth(size_t size) { + void **ptr = m_malloc0(size + 2 * sizeof(uintptr_t)); + if (MP_STATE_PORT(bluetooth_nimble_memory) != NULL) { + MP_STATE_PORT(bluetooth_nimble_memory)[0] = ptr; + } + ptr[0] = NULL; + ptr[1] = MP_STATE_PORT(bluetooth_nimble_memory); + MP_STATE_PORT(bluetooth_nimble_memory) = ptr; + return &ptr[2]; +} + +void m_free_bluetooth(void *ptr_in) { + void **ptr = &((void**)ptr_in)[-2]; + if (ptr[1] != NULL) { + ((void**)ptr[1])[0] = ptr[0]; + } + if (ptr[0] != NULL) { + ((void**)ptr[0])[1] = ptr[1]; + } else { + MP_STATE_PORT(bluetooth_nimble_memory) = ptr[1]; + } + m_free(ptr); +} + +// Check if a nimble ptr is tracked. +// If it isn't, that means that it's from a previous soft-reset cycle. +STATIC bool is_valid_nimble_malloc(void *ptr) { + DEBUG_MALLOC_printf("NIMBLE is_valid_nimble_malloc(%p)\n", ptr); + void** search = MP_STATE_PORT(bluetooth_nimble_memory); + while (search) { + if (&search[2] == ptr) { + return true; + } + + search = (void**)search[1]; + } + return false; +} + +void *nimble_malloc(size_t size) { + DEBUG_MALLOC_printf("NIMBLE malloc(%u)\n", (uint)size); + void* ptr = m_malloc_bluetooth(size); + DEBUG_MALLOC_printf(" --> %p\n", ptr); + return ptr; +} + +// Only free if it's still a valid pointer. +void nimble_free(void *ptr) { + DEBUG_MALLOC_printf("NIMBLE free(%p)\n", ptr); + if (ptr && is_valid_nimble_malloc(ptr)) { + m_free_bluetooth(ptr); + } +} + +// Only realloc if it's still a valid pointer. Otherwise just malloc. +void *nimble_realloc(void *ptr, size_t size) { + // This is only used by ble_gatts.c to grow the queue of pending services to be registered. + DEBUG_MALLOC_printf("NIMBLE realloc(%p, %u)\n", ptr, (uint)size); + void *ptr2 = nimble_malloc(size); + if (ptr && is_valid_nimble_malloc(ptr)) { + // If it's a realloc and we still have the old data, then copy it. + // This will happen as we add services. + memcpy(ptr2, ptr, size); + m_free_bluetooth(ptr); + } + return ptr2; +} + /******************************************************************************/ // EVENTQ diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 40db2f7560359..1a4e3c6902701 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -436,6 +436,7 @@ endif ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) include $(TOP)/extmod/nimble/nimble.mk +SRC_C += nimble.c SRC_C += nimble_hci_uart.c EXTMOD_SRC_C += extmod/modbluetooth_nimble.c ifeq ($(MICROPY_PY_NETWORK_CYW43),1) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 54e1c503c4f4b..5806755116f95 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -298,7 +298,8 @@ extern const struct _mp_obj_module_t mp_module_onewire; #endif #if MICROPY_BLUETOOTH_NIMBLE -#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE void **bluetooth_nimble_memory; +struct _mp_bluetooth_nimble_root_pointers_t; +#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE void **bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; #else #define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE #endif diff --git a/ports/stm32/nimble.c b/ports/stm32/nimble.c new file mode 100644 index 0000000000000..b8fdc8f8866ef --- /dev/null +++ b/ports/stm32/nimble.c @@ -0,0 +1,82 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" + +#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE + +#include "systick.h" +#include "pendsv.h" + +#include "transport/uart/ble_hci_uart.h" +#include "host/ble_hs.h" + +#include "extmod/modbluetooth_nimble.h" + +extern void nimble_uart_process(void); +extern void os_eventq_run_all(void); +extern void os_callout_process(void); + +// Hook for pendsv poller to run this periodically every 128ms +#define NIMBLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0) + +void nimble_poll(void) { + if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { + return; + } + + nimble_uart_process(); + os_callout_process(); + os_eventq_run_all(); +} + +void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms) { + if (NIMBLE_TICK(ticks_ms)) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll); + } +} + +void mp_bluetooth_nimble_port_preinit(void) { + MP_STATE_PORT(bluetooth_nimble_memory) = NULL; + ble_hci_uart_init(); +} + +void mp_bluetooth_nimble_port_postinit(void) { +} + +void mp_bluetooth_nimble_port_deinit(void) { + #ifdef pyb_pin_BT_REG_ON + mp_hal_pin_low(pyb_pin_BT_REG_ON); + #endif +} + +void mp_bluetooth_nimble_port_start(void) { + ble_hs_start(); +} + +#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE From 6a9bd1c1aba9f80844c0af96a73319797c6e81b8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 1 Oct 2019 23:47:37 +1000 Subject: [PATCH 0534/1299] esp32: Implement BLE using Nimble from IDF 4.x. --- ports/esp32/Makefile | 65 ++++++++++++++++++++++++++++++++ ports/esp32/boards/sdkconfig.ble | 6 +++ ports/esp32/mpconfigport.h | 18 +++++++++ ports/esp32/nimble.c | 57 ++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 ports/esp32/boards/sdkconfig.ble create mode 100644 ports/esp32/nimble.c diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 919a047eb6a87..f059536af95b6 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -174,6 +174,29 @@ INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/private_include INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include/esp_supplicant INC_ESPCOMP += -I$(ESPCOMP)/xtensa/include INC_ESPCOMP += -I$(ESPCOMP)/xtensa/esp32/include +ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) +INC_ESPCOMP += -I$(ESPCOMP)/bt/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/common/osi/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/common/btc/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/common/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/port/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/include +INC_ESPCOMP += -I$(ESPCOMP)/bt/host/nimble/esp-hci/include +endif else INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include INC_ESPCOMP += -I$(ESPCOMP)/expat/expat/expat/lib @@ -185,6 +208,17 @@ INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes endif +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +ifeq ($(MICROPY_PY_BLUETOOTH),1) +CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 +CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) +CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 +endif +endif +endif + # these flags are common to C and C++ compilation CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ -mlongcalls -nostdlib \ @@ -270,6 +304,7 @@ SRC_C = \ modnetwork.c \ network_lan.c \ network_ppp.c \ + nimble.c \ modsocket.c \ modesp.c \ esp32_partition.c \ @@ -286,6 +321,7 @@ SRC_C = \ EXTMOD_SRC_C = $(addprefix extmod/,\ modonewire.c \ + modbluetooth_nimble.c \ ) LIB_SRC_C = $(addprefix lib/,\ @@ -461,6 +497,31 @@ ESPIDF_ESP_EVENT_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_event/*.c)) ESPIDF_ESP_WIFI_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_wifi/src/*.c)) +ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) +ESPIDF_BT_NIMBLE_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/bt/controller/*.c) \ + $(wildcard $(ESPCOMP)/bt/common/btc/core/*.c) \ + $(wildcard $(ESPCOMP)/bt/common/osi/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/esp-hci/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/ext/tinycrypt/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ans/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/bas/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gap/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/gatt/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/ias/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/lls/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/services/tps/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/store/ram/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/host/util/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/nimble/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/nimble/src/*.c) \ + $(wildcard $(ESPCOMP)/bt/host/nimble/nimble/porting/npl/freertos/src/*.c) \ + ) +endif + $(BUILD)/$(ESPCOMP)/esp_eth/src/esp_eth_mac_dm9051.o: CFLAGS += -fno-strict-aliasing ESPIDF_ESP_ETH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/esp_eth/src/*.c)) @@ -521,6 +582,9 @@ ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) $(eval $(call gen_espidf_lib_rule,esp_common,$(ESPIDF_ESP_COMMON_O))) $(eval $(call gen_espidf_lib_rule,esp_event,$(ESPIDF_ESP_EVENT_O))) $(eval $(call gen_espidf_lib_rule,esp_wifi,$(ESPIDF_ESP_WIFI_O))) +ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) +$(eval $(call gen_espidf_lib_rule,bt_nimble,$(ESPIDF_BT_NIMBLE_O))) +endif $(eval $(call gen_espidf_lib_rule,esp_eth,$(ESPIDF_ESP_ETH_O))) $(eval $(call gen_espidf_lib_rule,xtensa,$(ESPIDF_XTENSA_O))) else @@ -636,6 +700,7 @@ APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ APP_LD_ARGS += $(LIBC_LIBM) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) APP_LD_ARGS += -L$(ESPCOMP)/xtensa/esp32 -lhal +APP_LD_ARGS += -L$(ESPCOMP)/bt/controller/lib -lbtdm_app APP_LD_ARGS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lsmartconfig -lcoexist else APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a diff --git a/ports/esp32/boards/sdkconfig.ble b/ports/esp32/boards/sdkconfig.ble new file mode 100644 index 0000000000000..db9cc1175245c --- /dev/null +++ b/ports/esp32/boards/sdkconfig.ble @@ -0,0 +1,6 @@ +# Note this requires building with IDF 4.x +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CTRL_MODE_BTDM= +CONFIG_BT_NIMBLE_ENABLED=y diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 63657741ce45f..5c9d602abcc27 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -162,6 +162,8 @@ void *esp_native_code_commit(void*, size_t); #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL) +#define MICROPY_PY_BLUETOOTH_RANDOM_ADDR (1) +#define MICROPY_PY_BLUETOOTH_DEFAULT_NAME ("ESP32") // fatfs configuration #define MICROPY_FATFS_ENABLE_LFN (1) @@ -189,8 +191,15 @@ extern const struct _mp_obj_module_t uos_module; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_network; +extern const struct _mp_obj_module_t mp_module_bluetooth; extern const struct _mp_obj_module_t mp_module_onewire; +#if MICROPY_PY_BLUETOOTH +#define BLUETOOTH_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_bluetooth), MP_ROM_PTR(&mp_module_bluetooth) }, +#else +#define BLUETOOTH_BUILTIN_MODULE +#endif + #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \ @@ -199,6 +208,7 @@ extern const struct _mp_obj_module_t mp_module_onewire; { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ + BLUETOOTH_BUILTIN_MODULE \ { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ @@ -224,10 +234,18 @@ extern const struct _mp_obj_module_t mp_module_onewire; struct _machine_timer_obj_t; +#if MICROPY_BLUETOOTH_NIMBLE +struct mp_bluetooth_nimble_root_pointers_t; +#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers; +#else +#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE +#endif + #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t machine_pin_irq_handler[40]; \ struct _machine_timer_obj_t *machine_timer_obj_head; \ + MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE // type definitions for the specific machine diff --git a/ports/esp32/nimble.c b/ports/esp32/nimble.c new file mode 100644 index 0000000000000..3747ae0f33aa3 --- /dev/null +++ b/ports/esp32/nimble.c @@ -0,0 +1,57 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jim Mussared + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/mphal.h" + +#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE + +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" + +STATIC void ble_host_task(void *param) { + nimble_port_run(); //This function will return only when nimble_port_stop() is executed. + nimble_port_freertos_deinit(); +} + +void mp_bluetooth_nimble_port_preinit(void) { + esp_nimble_hci_and_controller_init(); +} + +void mp_bluetooth_nimble_port_postinit(void) { + nimble_port_freertos_init(ble_host_task); +} + +void mp_bluetooth_nimble_port_deinit(void) { + nimble_port_stop(); +} + +void mp_bluetooth_nimble_port_start(void) { +} + +#endif From cd8bbf4cfca57f330f256134301e42f137f91eee Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 1 Oct 2019 23:47:55 +1000 Subject: [PATCH 0535/1299] esp32/boards: Enable BLE by default when building with IDF 4.x. --- ports/esp32/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index f059536af95b6..5d63a2586c542 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -110,6 +110,16 @@ $(info Add the xtensa toolchain to your PATH. See README.md) $(error C compiler missing) endif +# Support BLE by default when building with IDF 4.x. +# Can be explicitly disabled on the command line or board config. +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +MICROPY_PY_BLUETOOTH ?= 1 +ifeq ($(MICROPY_PY_BLUETOOTH),1) +SDKCONFIG += boards/sdkconfig.ble +MICROPY_BLUETOOTH_NIMBLE = 1 +endif +endif + # include sdkconfig to get needed configuration values include $(SDKCONFIG) From fa23033fc4b1b06e92ae5d0f6783257a6774318c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 8 Oct 2019 14:27:44 +1100 Subject: [PATCH 0536/1299] travis: Add BLE submodules to ESP32 IDF4 build. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 617cc2035ef35..7633b1a94c723 100644 --- a/.travis.yml +++ b/.travis.yml @@ -160,7 +160,7 @@ jobs: - make ${MAKEOPTS} -C ports/esp32 clean # IDF v4 build - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V4 :=" ports/esp32/Makefile | cut -d " " -f 3) - - git -C esp-idf submodule update --init components/esp_wifi/lib_esp32 components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls + - git -C esp-idf submodule update --init components/bt/controller/lib components/bt/host/nimble/nimble components/esp_wifi/lib_esp32 components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls - make ${MAKEOPTS} -C ports/esp32 # esp8266 port From 04fe62d06f0e0e56e7dc40bdf9883c7a2f2eac6a Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 27 Jun 2019 11:00:04 +1000 Subject: [PATCH 0537/1299] stm32/mboot: Add option to automatically reset when USB is disconnected. Enable in board config with: #define MBOOT_USB_RESET_ON_DISCONNECT (1) --- ports/stm32/mboot/main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c index a0f1f1eacec3d..015800ce438c9 100644 --- a/ports/stm32/mboot/main.c +++ b/ports/stm32/mboot/main.c @@ -1526,6 +1526,9 @@ void stm32_main(int initial_r0) { uint32_t ss = systick_ms; int ss2 = -1; #endif + #if MBOOT_USB_RESET_ON_DISCONNECT + bool has_connected = false; + #endif for (;;) { #if USE_USB_POLLING #if MBOOT_USB_AUTODETECT_PORT || MICROPY_HW_USB_MAIN_DEV == USB_PHY_FS_ID @@ -1559,6 +1562,15 @@ void stm32_main(int initial_r0) { led_state(LED0, 0); mp_hal_delay_ms(950); #endif + + #if MBOOT_USB_RESET_ON_DISCONNECT + if (pyb_usbdd.hUSBDDevice.dev_state == USBD_STATE_CONFIGURED) { + has_connected = true; + } + if (has_connected && pyb_usbdd.hUSBDDevice.dev_state == USBD_STATE_SUSPENDED) { + do_reset(); + } + #endif } } From 2863dcdf4f9f1fc421c7b745195259fbf46250a2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 8 Oct 2019 16:38:04 +1100 Subject: [PATCH 0538/1299] nrf: Add support to activate MICROPY_PY_SYS_STDFILES. Fixes issue #5162. --- ports/nrf/Makefile | 3 ++- ports/nrf/mphalport.c | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 1b70851eb868d..aa6c189aaac26 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -156,6 +156,7 @@ SRC_LIB += $(addprefix lib/,\ libc/string0.c \ mp-readline/readline.c \ utils/pyexec.c \ + utils/sys_stdio_mphal.c \ utils/interrupt_char.c \ timeutils/timeutils.c \ ) @@ -342,7 +343,7 @@ $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(Q)$(SIZE) $@ # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) +SRC_QSTR += $(SRC_C) $(SRC_LIB) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) # Append any auto-generated sources that are needed by sources listed in # SRC_QSTR diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index a050df147087c..bf89697083c07 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -30,6 +30,7 @@ #include "py/mphal.h" #include "py/mperrno.h" #include "py/runtime.h" +#include "py/stream.h" #include "uart.h" #include "nrfx_errors.h" #include "nrfx_config.h" @@ -53,6 +54,15 @@ void mp_hal_set_interrupt_char(int c) { #endif #if !MICROPY_PY_BLE_NUS +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + uintptr_t ret = 0; + if ((poll_flags & MP_STREAM_POLL_RD) && MP_STATE_PORT(board_stdio_uart) != NULL + && uart_rx_any(MP_STATE_PORT(board_stdio_uart))) { + ret |= MP_STREAM_POLL_RD; + } + return ret; +} + int mp_hal_stdin_rx_chr(void) { for (;;) { if (MP_STATE_PORT(board_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(board_stdio_uart))) { From 53a9b45da1f7f625e273125c259bad7793f17e47 Mon Sep 17 00:00:00 2001 From: Mike Causer Date: Wed, 18 Sep 2019 15:08:06 +1000 Subject: [PATCH 0539/1299] esp8266: Add per-board configs, following other ports. The specific board can be selected with the BOARD makefile variable. This defaults (if not specified) to BOARD=GENERIC, which is the original default firmware build. For the 512k target use BOARD=GENERIC_512K. --- ports/esp8266/Makefile | 34 ++++++++++----- ports/esp8266/README.md | 31 +++++++------ ports/esp8266/boards/GENERIC/mpconfigboard.h | 21 +++++++++ .../boards/GENERIC_512K/mpconfigboard.h | 4 ++ .../boards/GENERIC_512K/mpconfigboard.mk | 3 ++ .../esp8266/{ => boards}/eagle.rom.addr.v6.ld | 0 ports/esp8266/{ => boards}/esp8266.ld | 2 +- ports/esp8266/{ => boards}/esp8266_512k.ld | 2 +- ports/esp8266/{ => boards}/esp8266_common.ld | 6 +-- ports/esp8266/{ => boards}/esp8266_ota.ld | 2 +- ports/esp8266/mpconfigport.h | 25 +++-------- ports/esp8266/mpconfigport_512k.h | 43 ------------------- 12 files changed, 83 insertions(+), 90 deletions(-) create mode 100644 ports/esp8266/boards/GENERIC/mpconfigboard.h create mode 100644 ports/esp8266/boards/GENERIC_512K/mpconfigboard.h create mode 100644 ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk rename ports/esp8266/{ => boards}/eagle.rom.addr.v6.ld (100%) rename ports/esp8266/{ => boards}/esp8266.ld (89%) rename ports/esp8266/{ => boards}/esp8266_512k.ld (89%) rename ports/esp8266/{ => boards}/esp8266_common.ld (98%) rename ports/esp8266/{ => boards}/esp8266_ota.ld (92%) delete mode 100644 ports/esp8266/mpconfigport_512k.h diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 2162c72f075d7..8cac07afccd8e 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -1,13 +1,29 @@ +# Select the board to build for: if not given on the command line, +# then default to GENERIC. +BOARD ?= GENERIC + +# If the build directory is not given, make it reflect the board name. +BUILD ?= build-$(BOARD) + +BOARD_DIR ?= boards/$(BOARD) +ifeq ($(wildcard $(BOARD_DIR)/.),) +$(error Invalid BOARD specified: $(BOARD_DIR)) +endif + include ../../py/mkenv.mk +# Optional +-include $(BOARD_DIR)/mpconfigboard.mk + # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h +QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h MICROPY_PY_USSL = 1 MICROPY_SSL_AXTLS = 1 AXTLS_DEFS_EXTRA = -Dabort=abort_ -DRT_MAX_PLAIN_LENGTH=1024 -DRT_EXTRA=4096 -MICROPY_FATFS = 1 -MICROPY_PY_BTREE = 1 +MICROPY_FATFS ?= 1 +MICROPY_PY_BTREE ?= 1 BTREE_DEFS_EXTRA = -DDEFPSIZE=1024 -DMINCACHE=3 FROZEN_DIR ?= scripts @@ -40,10 +56,10 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \ -DLWIP_OPEN_SRC CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \ - $(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) + $(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR) -LDSCRIPT = esp8266.ld -LDFLAGS = -nostdlib -T $(LDSCRIPT) -Map=$(@:.elf=.map) --cref +LD_FILES ?= boards/esp8266.ld +LDFLAGS = -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD) LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) @@ -92,6 +108,7 @@ SRC_C = \ fatfs_port.c \ posix_helpers.c \ hspi.c \ + $(wildcard $(BOARD_DIR)/*.c) \ $(SRC_MOD) EXTMOD_SRC_C = $(addprefix extmod/,\ @@ -192,15 +209,12 @@ $(BUILD)/firmware.elf: $(OBJ) $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) $(Q)$(SIZE) $@ -512k: - $(MAKE) LDSCRIPT=esp8266_512k.ld CFLAGS_EXTRA='-DMP_CONFIGFILE=""' MICROPY_FATFS=0 MICROPY_PY_BTREE=0 - ota: rm -f $(BUILD)/firmware.elf $(BUILD)/firmware.elf*.bin - $(MAKE) LDSCRIPT=esp8266_ota.ld FWBIN=$(BUILD)/firmware-ota.bin + $(MAKE) LD_FILES=boards/esp8266_ota.ld FWBIN=$(BUILD)/firmware-ota.bin include $(TOP)/py/mkrules.mk clean-modules: git clean -f -d modules - rm -f build/frozen*.c + rm -f $(BUILD)/frozen*.c diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md index 402798928c883..9541dfd22b18e 100644 --- a/ports/esp8266/README.md +++ b/ports/esp8266/README.md @@ -52,12 +52,11 @@ Then, to build MicroPython for the ESP8266, just run: $ cd ports/esp8266 $ make ``` -This will produce binary images in the `build/` subdirectory. If you install -MicroPython to your module for the first time, or after installing any other -firmware, you should erase flash completely: - -``` -esptool.py --port /dev/ttyXXX erase_flash +This will produce binary images in the `build-GENERIC/` subdirectory. If you +install MicroPython to your module for the first time, or after installing any +other firmware, you should erase flash completely: +```bash +$ esptool.py --port /dev/ttyXXX erase_flash ``` Erase flash also as a troubleshooting measure, if a module doesn't behave as @@ -76,17 +75,25 @@ that flash size is in megabits): $ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy ``` -The image produced is `build/firmware-combined.bin`, to be flashed at 0x00000. +The image produced is `build-GENERIC/firmware-combined.bin`, to be flashed at 0x00000. + +The default board definition is the directory `boards/GENERIC`. +For a custom configuration you can define your own board in the directory `boards/`. + +The `BOARD` variable can be set on the make command line, for example: +```bash +$ make BOARD=GENERIC_512K +``` __512KB FlashROM version__ The normal build described above requires modules with at least 1MB of FlashROM onboard. There's a special configuration for 512KB modules, which can be -built with `make 512k`. This configuration is highly limited, lacks filesystem -support, WebREPL, and has many other features disabled. It's mostly suitable -for advanced users who are interested to fine-tune options to achieve a required -setup. If you are an end user, please consider using a module with at least 1MB -of FlashROM. +built with `make BOARD=GENERIC_512K`. This configuration is highly limited, lacks +filesystem support, WebREPL, and has many other features disabled. It's mostly +suitable for advanced users who are interested to fine-tune options to achieve a +required setup. If you are an end user, please consider using a module with at +least 1MB of FlashROM. First start ----------- diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.h b/ports/esp8266/boards/GENERIC/mpconfigboard.h new file mode 100644 index 0000000000000..a7cacb815ee35 --- /dev/null +++ b/ports/esp8266/boards/GENERIC/mpconfigboard.h @@ -0,0 +1,21 @@ +#define MICROPY_HW_BOARD_NAME "ESP module" +#define MICROPY_HW_MCU_NAME "ESP8266" + +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_EMIT_XTENSA (1) +#define MICROPY_EMIT_INLINE_XTENSA (1) + +#define MICROPY_DEBUG_PRINTERS (1) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) + +#define MICROPY_READER_VFS (MICROPY_VFS) +#define MICROPY_VFS (1) +#define MICROPY_VFS_FAT (1) + +#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) +#define MICROPY_PY_ALL_SPECIAL_METHODS (1) +#define MICROPY_PY_IO_FILEIO (1) +#define MICROPY_PY_SYS_STDIO_BUFFER (1) +#define MICROPY_PY_URE_SUB (1) +#define MICROPY_PY_UCRYPTOLIB (1) +#define MICROPY_PY_FRAMEBUF (1) diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h new file mode 100644 index 0000000000000..0693232aa1fb6 --- /dev/null +++ b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h @@ -0,0 +1,4 @@ +#define MICROPY_HW_BOARD_NAME "ESP module (512K)" +#define MICROPY_HW_MCU_NAME "ESP8266" + +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk new file mode 100644 index 0000000000000..90f3c1773de87 --- /dev/null +++ b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk @@ -0,0 +1,3 @@ +MICROPY_FATFS = 0 +MICROPY_PY_BTREE = 0 +LD_FILES = boards/esp8266_512k.ld diff --git a/ports/esp8266/eagle.rom.addr.v6.ld b/ports/esp8266/boards/eagle.rom.addr.v6.ld similarity index 100% rename from ports/esp8266/eagle.rom.addr.v6.ld rename to ports/esp8266/boards/eagle.rom.addr.v6.ld diff --git a/ports/esp8266/esp8266.ld b/ports/esp8266/boards/esp8266.ld similarity index 89% rename from ports/esp8266/esp8266.ld rename to ports/esp8266/boards/esp8266.ld index deeb82b456122..745edaadbb3b5 100644 --- a/ports/esp8266/esp8266.ld +++ b/ports/esp8266/boards/esp8266.ld @@ -9,4 +9,4 @@ MEMORY } /* define common sections and symbols */ -INCLUDE esp8266_common.ld +INCLUDE boards/esp8266_common.ld diff --git a/ports/esp8266/esp8266_512k.ld b/ports/esp8266/boards/esp8266_512k.ld similarity index 89% rename from ports/esp8266/esp8266_512k.ld rename to ports/esp8266/boards/esp8266_512k.ld index 0ae663db11e29..8690447813946 100644 --- a/ports/esp8266/esp8266_512k.ld +++ b/ports/esp8266/boards/esp8266_512k.ld @@ -9,4 +9,4 @@ MEMORY } /* define common sections and symbols */ -INCLUDE esp8266_common.ld +INCLUDE boards/esp8266_common.ld diff --git a/ports/esp8266/esp8266_common.ld b/ports/esp8266/boards/esp8266_common.ld similarity index 98% rename from ports/esp8266/esp8266_common.ld rename to ports/esp8266/boards/esp8266_common.ld index bbbb1325e1147..ce67e48048978 100644 --- a/ports/esp8266/esp8266_common.ld +++ b/ports/esp8266/boards/esp8266_common.ld @@ -142,7 +142,7 @@ SECTIONS *lib/utils/interrupt_char.o*(.literal.mp_hal_set_interrupt_char, .text.mp_hal_set_interrupt_char) *drivers/bus/*.o(.literal* .text*) - build/main.o(.literal* .text*) + build-*/main.o(.literal* .text*) *fatfs_port.o(.literal* .text*) *gccollect.o(.literal* .text*) *gchelper.o(.literal* .text*) @@ -179,7 +179,7 @@ SECTIONS */frozen.o(.rodata.mp_frozen_content) /* frozen modules */ /* for -mforce-l32 */ - build/*.o(.rodata*) + build-*/*.o(.rodata*) _irom0_text_end = ABSOLUTE(.); } >irom0_0_seg :irom0_0_phdr @@ -313,4 +313,4 @@ SECTIONS } /* get ROM code address */ -INCLUDE "eagle.rom.addr.v6.ld" +INCLUDE "boards/eagle.rom.addr.v6.ld" diff --git a/ports/esp8266/esp8266_ota.ld b/ports/esp8266/boards/esp8266_ota.ld similarity index 92% rename from ports/esp8266/esp8266_ota.ld rename to ports/esp8266/boards/esp8266_ota.ld index 604480a0a9630..7fdf6abef00e3 100644 --- a/ports/esp8266/esp8266_ota.ld +++ b/ports/esp8266/boards/esp8266_ota.ld @@ -10,4 +10,4 @@ MEMORY } /* define common sections and symbols */ -INCLUDE esp8266_common.ld +INCLUDE boards/esp8266_common.ld diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 5a1ca098d8504..fa809d91a6513 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -1,6 +1,10 @@ -#include +// Options to control how MicroPython is built for this port, +// overriding defaults in py/mpconfig.h. + +// Board-specific definitions +#include "mpconfigboard.h" -// options to control how MicroPython is built +#include #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) #define MICROPY_GC_STACK_ENTRY_TYPE uint16_t @@ -10,13 +14,8 @@ #define MICROPY_ALLOC_PARSE_RULE_INC (8) #define MICROPY_ALLOC_PARSE_RESULT_INC (8) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) -#define MICROPY_PERSISTENT_CODE_LOAD (1) -#define MICROPY_EMIT_XTENSA (1) -#define MICROPY_EMIT_INLINE_XTENSA (1) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTER (&mp_debug_print) -#define MICROPY_DEBUG_PRINTERS (1) -#define MICROPY_READER_VFS (MICROPY_VFS) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) @@ -32,7 +31,6 @@ #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_PY_DESCRIPTORS (1) -#define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) @@ -40,7 +38,6 @@ #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_ROUND_INT (1) #define MICROPY_PY_BUILTINS_INPUT (1) @@ -58,25 +55,21 @@ #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (1) #define MICROPY_PY_IO_IOBASE (1) -#define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (1) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) -#define MICROPY_PY_SYS_STDIO_BUFFER (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UHASHLIB (1) #define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS) -#define MICROPY_PY_UCRYPTOLIB (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UTIMEQ (1) #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URE (1) -#define MICROPY_PY_URE_SUB (1) #define MICROPY_PY_USELECT (1) #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_UZLIB (1) @@ -92,13 +85,11 @@ #define MICROPY_PY_WEBREPL (1) #define MICROPY_PY_WEBREPL_DELAY (20) #define MICROPY_PY_WEBREPL_STATIC_FILEBUF (1) -#define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_OS_DUPTERM (2) #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) #define MICROPY_WARNINGS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) #define MICROPY_STREAMS_NON_BLOCK (1) @@ -108,12 +99,10 @@ #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32 #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool -#define MICROPY_VFS (1) #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_VFS_FAT (1) #define MICROPY_ESP8266_APA102 (1) #define MICROPY_ESP8266_NEOPIXEL (1) @@ -211,8 +200,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; // board specifics #define MICROPY_MPHALPORT_H "esp_mphal.h" -#define MICROPY_HW_BOARD_NAME "ESP module" -#define MICROPY_HW_MCU_NAME "ESP8266" #define MICROPY_PY_SYS_PLATFORM "esp8266" #define MP_FASTCODE(n) __attribute__((section(".iram0.text." #n))) n diff --git a/ports/esp8266/mpconfigport_512k.h b/ports/esp8266/mpconfigport_512k.h deleted file mode 100644 index df670d4c96b72..0000000000000 --- a/ports/esp8266/mpconfigport_512k.h +++ /dev/null @@ -1,43 +0,0 @@ -#include - -#undef MICROPY_EMIT_XTENSA -#define MICROPY_EMIT_XTENSA (0) -#undef MICROPY_EMIT_INLINE_XTENSA -#define MICROPY_EMIT_INLINE_XTENSA (0) - -#undef MICROPY_DEBUG_PRINTERS -#define MICROPY_DEBUG_PRINTERS (0) - -#undef MICROPY_ERROR_REPORTING -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) - -#undef MICROPY_VFS -#define MICROPY_VFS (0) -#undef MICROPY_VFS_FAT -#define MICROPY_VFS_FAT (0) - -#undef MICROPY_PERSISTENT_CODE_LOAD -#define MICROPY_PERSISTENT_CODE_LOAD (0) - -#undef MICROPY_PY_IO_FILEIO -#define MICROPY_PY_IO_FILEIO (0) - -#undef MICROPY_PY_SYS_STDIO_BUFFER -#define MICROPY_PY_SYS_STDIO_BUFFER (0) -#undef MICROPY_PY_BUILTINS_SLICE_ATTRS -#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) -#undef MICROPY_PY_ALL_SPECIAL_METHODS -#define MICROPY_PY_ALL_SPECIAL_METHODS (0) - -#undef MICROPY_PY_FRAMEBUF -#define MICROPY_PY_FRAMEBUF (0) - -#undef MICROPY_PY_URE_SUB -#define MICROPY_PY_URE_SUB (0) - -#undef MICROPY_PY_UCRYPTOLIB -#define MICROPY_PY_UCRYPTOLIB (0) - -#undef mp_import_stat -#undef mp_builtin_open -#undef mp_builtin_open_obj From 3117fde407064cd6e51c4f4bdd35ac9ca3cca20f Mon Sep 17 00:00:00 2001 From: Mike Causer Date: Mon, 30 Sep 2019 17:26:41 +1000 Subject: [PATCH 0540/1299] travis: Add esp8266 GENERIC_512K build to CI. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7633b1a94c723..cc015bda3973e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -174,6 +174,7 @@ jobs: - git submodule update --init lib/axtls lib/berkeley-db-1.xx - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/esp8266 + - make ${MAKEOPTS} -C ports/esp8266 BOARD=GENERIC_512K # nrf port - stage: test From 305f537bf940fbbe3474cd1e0938586426d25b48 Mon Sep 17 00:00:00 2001 From: Andrey Belykh Date: Fri, 4 Oct 2019 23:27:14 -0400 Subject: [PATCH 0541/1299] stm32/sdcard: Support boards with no SD card detect pin. If MICROPY_HW_SDCARD_DETECT_PIN is not defined then the SD card will always be detected as present. --- ports/stm32/sdcard.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index f54d67ea496db..44b1c807d8e08 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -175,7 +175,9 @@ void sdcard_init(void) { // configure the SD card detect pin // we do this here so we can detect if the SD card is inserted before powering it on + #if defined(MICROPY_HW_SDCARD_DETECT_PIN) mp_hal_pin_config(MICROPY_HW_SDCARD_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_SDCARD_DETECT_PULL, 0); + #endif } STATIC void sdmmc_msp_init(void) { @@ -231,7 +233,11 @@ bool sdcard_is_present(void) { return false; } #endif + #if defined(MICROPY_HW_SDCARD_DETECT_PIN) return HAL_GPIO_ReadPin(MICROPY_HW_SDCARD_DETECT_PIN->gpio, MICROPY_HW_SDCARD_DETECT_PIN->pin_mask) == MICROPY_HW_SDCARD_DETECT_PRESENT; + #else + return true; + #endif } #if MICROPY_HW_ENABLE_SDCARD From 580a2656d10cc7c1fc93e094d7eb71f04d99c329 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 9 Oct 2019 22:59:35 +1100 Subject: [PATCH 0542/1299] stm32: Use hardware double sqrt on F7/H7 MCUs. Identical to cd527bb324ade952d11a134859d38bf5272c165e but for doubles. This gives a -2.754% improvement on bm_float.py, and -35% improvement on calling sqrt in a loop. --- lib/libm_dbl/thumb_vfp_sqrt.c | 10 ++++++++++ ports/stm32/Makefile | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 lib/libm_dbl/thumb_vfp_sqrt.c diff --git a/lib/libm_dbl/thumb_vfp_sqrt.c b/lib/libm_dbl/thumb_vfp_sqrt.c new file mode 100644 index 0000000000000..dd37a07b053c5 --- /dev/null +++ b/lib/libm_dbl/thumb_vfp_sqrt.c @@ -0,0 +1,10 @@ +// an implementation of sqrt for Thumb using hardware double-precision VFP instructions + +double sqrt(double x) { + double ret; + asm volatile ( + "vsqrt.f64 %P0, %P1\n" + : "=w" (ret) + : "w" (x)); + return ret; +} diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 1a4e3c6902701..28b90199aef2f 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -173,12 +173,16 @@ SRC_LIBM = $(addprefix lib/libm_dbl/,\ scalbn.c \ sin.c \ sinh.c \ - sqrt.c \ tan.c \ tanh.c \ tgamma.c \ trunc.c \ ) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f7 h7)) +SRC_LIBM += lib/libm_dbl/thumb_vfp_sqrt.c +else +SRC_LIBM += lib/libm_dbl/sqrt.c +endif else SRC_LIBM = $(addprefix lib/libm/,\ math.c \ From 79ab82ea77b0a924e96c2f6333e00c97706971ab Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Oct 2019 18:05:56 +1100 Subject: [PATCH 0543/1299] esp8266/modules/ntptime.py: Always close socket, and set day-of-week. Fixes issue #5189. --- ports/esp8266/modules/ntptime.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ports/esp8266/modules/ntptime.py b/ports/esp8266/modules/ntptime.py index 85c754af6c4b3..1a1da65357b9b 100644 --- a/ports/esp8266/modules/ntptime.py +++ b/ports/esp8266/modules/ntptime.py @@ -17,10 +17,12 @@ def time(): NTP_QUERY[0] = 0x1b addr = socket.getaddrinfo(host, 123)[0][-1] s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.settimeout(1) - res = s.sendto(NTP_QUERY, addr) - msg = s.recv(48) - s.close() + try: + s.settimeout(1) + res = s.sendto(NTP_QUERY, addr) + msg = s.recv(48) + finally: + s.close() val = struct.unpack("!I", msg[40:44])[0] return val - NTP_DELTA @@ -31,5 +33,4 @@ def settime(): import machine import utime tm = utime.localtime(t) - tm = tm[0:3] + (0,) + tm[3:6] + (0,) - machine.RTC().datetime(tm) + machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0)) From 1571120dc2c32d1eff451d6d52fde38dbec1d114 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Wed, 9 Oct 2019 19:34:16 +0200 Subject: [PATCH 0544/1299] nrf/device: Correct SPIM3 IRQ handler entry for nrf52840. --- ports/nrf/device/startup_nrf52840.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/nrf/device/startup_nrf52840.c b/ports/nrf/device/startup_nrf52840.c index 0935d7d1d02a0..288b13820f534 100644 --- a/ports/nrf/device/startup_nrf52840.c +++ b/ports/nrf/device/startup_nrf52840.c @@ -176,7 +176,9 @@ const func __Vectors[] __attribute__ ((section(".isr_vector"),used)) = { UARTE1_IRQHandler, QSPI_IRQHandler, CRYPTOCELL_IRQHandler, - SPIM3_IRQHandler, + 0, 0, PWM3_IRQHandler, + 0, + SPIM3_IRQHandler, }; From 60b0b69f202f552c89c7ccc74a8304549f85c4fa Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Wed, 9 Oct 2019 20:01:51 +0200 Subject: [PATCH 0545/1299] nrf: Add tinyusb support for nrf52840. Add nrf-port finyusb driver files. USB CDC can be activated by board configuration files using the MICROPY_HW_USB_CDC. Updating BLE driver, Makefile, nrfx-glue and main.c to plug in the tinyusb stack. --- ports/nrf/Makefile | 31 ++++ ports/nrf/drivers/bluetooth/ble_drv.c | 8 + ports/nrf/drivers/usb/tusb_config.h | 44 +++++ ports/nrf/drivers/usb/usb_cdc.c | 226 ++++++++++++++++++++++++ ports/nrf/drivers/usb/usb_cdc.h | 40 +++++ ports/nrf/drivers/usb/usb_descriptors.c | 114 ++++++++++++ ports/nrf/main.c | 11 +- ports/nrf/mphalport.c | 2 + ports/nrf/nrfx_config.h | 8 + ports/nrf/nrfx_glue.h | 2 + 10 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 ports/nrf/drivers/usb/tusb_config.h create mode 100644 ports/nrf/drivers/usb/usb_cdc.c create mode 100644 ports/nrf/drivers/usb/usb_cdc.h create mode 100644 ports/nrf/drivers/usb/usb_descriptors.c diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index aa6c189aaac26..46dd8c8d71be2 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -66,6 +66,7 @@ INC += -I../../lib/nrfx/drivers INC += -I../../lib/nrfx/drivers/include INC += -I../../lib/nrfx/mdk INC += -I../../lib/nrfx/hal +INC += -I../../lib/nrfx/drivers/src/ MCU_VARIANT_UPPER = $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') MCU_SUB_VARIANT_UPPER = $(shell echo $(MCU_SUB_VARIANT) | tr '[:lower:]' '[:upper:]') @@ -183,6 +184,8 @@ SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ nrfx_pwm.c \ nrfx_gpiote.c \ nrfx_nvmc.c \ + nrfx_power.c \ + nrfx_clock.c \ ) SRC_C += \ @@ -198,6 +201,34 @@ SRC_C += \ drivers/bluetooth/ble_drv.c \ drivers/bluetooth/ble_uart.c \ +ifeq ($(MCU_SUB_VARIANT), nrf52840) + +INC += -I./drivers/usb +INC += -I../../lib/tinyusb/src + + +# If SoftDevice is selected. +ifneq ($(SD), ) +# For external tinyusb drivers to enable SoftDevice mode. +CFLAGS += -DSOFTDEVICE_PRESENT +endif + +SRC_C += $(addprefix drivers/usb/,\ + usb_cdc.c \ + usb_descriptors.c \ + ) + +SRC_C += $(addprefix lib/tinyusb/src/,\ + common/tusb_fifo.c \ + device/usbd.c \ + device/usbd_control.c \ + class/cdc/cdc_device.c \ + tusb.c \ + portable/nordic/nrf5x/dcd_nrf5x.c \ + portable/nordic/nrf5x/hal_nrf5x.c \ + ) +endif + DRIVERS_SRC_C += $(addprefix modules/,\ machine/modmachine.c \ machine/uart.c \ diff --git a/ports/nrf/drivers/bluetooth/ble_drv.c b/ports/nrf/drivers/bluetooth/ble_drv.c index e01d118487c77..4401369f8be22 100644 --- a/ports/nrf/drivers/bluetooth/ble_drv.c +++ b/ports/nrf/drivers/bluetooth/ble_drv.c @@ -40,6 +40,10 @@ #include "mphalport.h" +#if MICROPY_HW_USB_CDC +#include "usb_cdc.h" +#endif + #define BLE_DRIVER_VERBOSE 0 #if BLE_DRIVER_VERBOSE @@ -952,6 +956,10 @@ static void sd_evt_handler(uint32_t evt_id) { // unhandled event! break; } +#if MICROPY_HW_USB_CDC + // Farward SOC events to USB CDC driver. + usb_cdc_sd_event_handler(evt_id); +#endif } static void ble_evt_handler(ble_evt_t * p_ble_evt) { diff --git a/ports/nrf/drivers/usb/tusb_config.h b/ports/nrf/drivers/usb/tusb_config.h new file mode 100644 index 0000000000000..619578ad6ee3a --- /dev/null +++ b/ports/nrf/drivers/usb/tusb_config.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_NRF_TUSB_CONFIG_H +#define MICROPY_INCLUDED_NRF_TUSB_CONFIG_H + +// Common configuration + +#define CFG_TUSB_MCU OPT_MCU_NRF5X +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + +#define CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) + +// Device configuration + +#define CFG_TUD_ENDOINT0_SIZE (64) +#define CFG_TUD_CDC (1) +#define CFG_TUD_CDC_RX_BUFSIZE (64) +#define CFG_TUD_CDC_TX_BUFSIZE (64) + +#endif // MICROPY_INCLUDED_NRF_TUSB_CONFIG_H diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c new file mode 100644 index 0000000000000..c90bced6bb563 --- /dev/null +++ b/ports/nrf/drivers/usb/usb_cdc.c @@ -0,0 +1,226 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2019 Glenn Ruben Bakke + * + * 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 file is part of the TinyUSB stack. + */ + +#include "py/mphal.h" + +#if MICROPY_HW_USB_CDC + +#include "tusb.h" +#include "nrfx.h" +#include "nrfx_power.h" +#include "nrfx_uart.h" +#include "py/ringbuf.h" + +#ifdef BLUETOOTH_SD +#include "nrf_sdm.h" +#include "nrf_soc.h" +#include "ble_drv.h" +#endif + +extern void tusb_hal_nrf_power_event(uint32_t event); + +static void cdc_task(void); + +static uint8_t rx_ringbuf_array[1024]; +static uint8_t tx_ringbuf_array[1024]; +static volatile ringbuf_t rx_ringbuf; +static volatile ringbuf_t tx_ringbuf; + +static void board_init(void) { + // Config clock source. +#ifndef BLUETOOTH_SD + NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk); + NRF_CLOCK->TASKS_LFCLKSTART = 1UL; +#endif + + // Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice + // 2 is highest for application + NRFX_IRQ_PRIORITY_SET(USBD_IRQn, 2); + + // USB power may already be ready at this time -> no event generated + // We need to invoke the handler based on the status initially + uint32_t usb_reg; + +#ifdef BLUETOOTH_SD + uint8_t sd_en = false; + sd_softdevice_is_enabled(&sd_en); + + if (sd_en) { + sd_power_usbdetected_enable(true); + sd_power_usbpwrrdy_enable(true); + sd_power_usbremoved_enable(true); + + sd_power_usbregstatus_get(&usb_reg); + } else +#endif + { + // Power module init + const nrfx_power_config_t pwr_cfg = { 0 }; + nrfx_power_init(&pwr_cfg); + + // Register tusb function as USB power handler + const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event }; + nrfx_power_usbevt_init(&config); + + nrfx_power_usbevt_enable(); + + usb_reg = NRF_POWER->USBREGSTATUS; + } + + if (usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); + } + +#ifndef BLUETOOTH_SD + if (usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); + } +#endif +} + +static bool cdc_rx_any(void) { + return rx_ringbuf.iput != rx_ringbuf.iget; +} + +static int cdc_rx_char(void) { + return ringbuf_get((ringbuf_t*)&rx_ringbuf); +} + +static bool cdc_tx_any(void) { + return tx_ringbuf.iput != tx_ringbuf.iget; +} + +static int cdc_tx_char(void) { + return ringbuf_get((ringbuf_t*)&tx_ringbuf); +} + +static void cdc_task(void) +{ + if ( tud_cdc_connected() ) { + // connected and there are data available + while (tud_cdc_available()) { + int c; + uint32_t count = tud_cdc_read(&c, 1); + (void)count; + ringbuf_put((ringbuf_t*)&rx_ringbuf, c); + } + + int chars = 0; + while (cdc_tx_any()) { + if (chars < 64) { + tud_cdc_write_char(cdc_tx_char()); + chars++; + } else { + chars = 0; + tud_cdc_write_flush(); + } + } + + tud_cdc_write_flush(); + } +} + +static void usb_cdc_loop(void) { + tud_task(); + cdc_task(); +} + +int usb_cdc_init(void) +{ + static bool initialized = false; + if (!initialized) { + +#if BLUETOOTH_SD + // Initialize the clock and BLE stack. + ble_drv_stack_enable(); +#endif + + board_init(); + initialized = true; + } + + rx_ringbuf.buf = rx_ringbuf_array; + rx_ringbuf.size = sizeof(rx_ringbuf_array); + rx_ringbuf.iget = 0; + rx_ringbuf.iput = 0; + + tx_ringbuf.buf = tx_ringbuf_array; + tx_ringbuf.size = sizeof(tx_ringbuf_array); + tx_ringbuf.iget = 0; + tx_ringbuf.iput = 0; + + tusb_init(); + + return 0; +} + +#ifdef BLUETOOTH_SD +// process SOC event from SD +void usb_cdc_sd_event_handler(uint32_t soc_evt) { + /*------------- usb power event handler -------------*/ + int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED: + (soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY : + (soc_evt == NRF_EVT_POWER_USB_REMOVED ) ? NRFX_POWER_USB_EVT_REMOVED : -1; + + if (usbevt >= 0) { + tusb_hal_nrf_power_event(usbevt); + } +} +#endif + +int mp_hal_stdin_rx_chr(void) { + for (;;) { + usb_cdc_loop(); + if (cdc_rx_any()) { + return cdc_rx_char(); + } + } + + return 0; +} + +void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + + for (const char *top = str + len; str < top; str++) { + ringbuf_put((ringbuf_t*)&tx_ringbuf, *str); + usb_cdc_loop(); + } +} + +void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { + + for (const char *top = str + len; str < top; str++) { + if (*str == '\n') { + ringbuf_put((ringbuf_t*)&tx_ringbuf, '\r'); + usb_cdc_loop(); + } + ringbuf_put((ringbuf_t*)&tx_ringbuf, *str); + usb_cdc_loop(); + } +} + +#endif // MICROPY_HW_USB_CDC diff --git a/ports/nrf/drivers/usb/usb_cdc.h b/ports/nrf/drivers/usb/usb_cdc.h new file mode 100644 index 0000000000000..7cd94f85ba27b --- /dev/null +++ b/ports/nrf/drivers/usb/usb_cdc.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NRF_DRIVERS_USB_CDC_H__ +#define NRF_DRIVERS_USB_CDC_H__ + +#include "tusb.h" + +void usb_cdc_init(void); + +void usb_cdc_loop(void); +int usb_cdc_read_char(void); +void usb_cdc_write_char(char c); + +void usb_cdc_sd_event_handler(uint32_t soc_evt); + +#endif // NRF_DRIVERS_USB_CDC_H__ diff --git a/ports/nrf/drivers/usb/usb_descriptors.c b/ports/nrf/drivers/usb/usb_descriptors.c new file mode 100644 index 0000000000000..a061302d6b299 --- /dev/null +++ b/ports/nrf/drivers/usb/usb_descriptors.c @@ -0,0 +1,114 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "tusb.h" + +#define USBD_VID (0xf055) +#define USBD_PID (0x9802) + +#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) +#define USBD_MAX_POWER_MA (250) + +#define USBD_ITF_CDC (0) // needs 2 interfaces +#define USBD_ITF_MAX (2) + +#define USBD_CDC_EP_CMD (0x81) +#define USBD_CDC_EP_OUT (0x02) +#define USBD_CDC_EP_IN (0x82) +#define USBD_CDC_CMD_MAX_SIZE (8) + +#define USBD_STR_0 (0x00) +#define USBD_STR_MANUF (0x01) +#define USBD_STR_PRODUCT (0x02) +#define USBD_STR_SERIAL (0x03) +#define USBD_STR_CDC (0x04) + +// Note: descriptors returned from callbacks must exist long enough for transfer to complete + +static const tusb_desc_device_t usbd_desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100, + .iManufacturer = USBD_STR_MANUF, + .iProduct = USBD_STR_PRODUCT, + .iSerialNumber = USBD_STR_SERIAL, + .bNumConfigurations = 1, +}; + +static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { + TUD_CONFIG_DESCRIPTOR(USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA), + + TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, + USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, CFG_TUD_CDC_RX_BUFSIZE), +}; + +static const char *const usbd_desc_str[] = { + [USBD_STR_MANUF] = "MicroPython", + [USBD_STR_PRODUCT] = "Board in FS mode", + [USBD_STR_SERIAL] = "000000000000", // TODO + [USBD_STR_CDC] = "Board CDC", +}; + +const uint8_t *tud_descriptor_device_cb(void) { + return (const uint8_t*)&usbd_desc_device; +} + +const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; + return usbd_desc_cfg; +} + +const uint16_t *tud_descriptor_string_cb(uint8_t index) { + #define DESC_STR_MAX (20) + static uint16_t desc_str[DESC_STR_MAX]; + + uint8_t len; + if (index == 0) { + desc_str[1] = 0x0409; // supported language is English + len = 1; + } else { + if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { + return NULL; + } + const char* str = usbd_desc_str[index]; + for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { + desc_str[1 + len] = str[len]; + } + } + + // first byte is len, second byte is string type + desc_str[0] = TUD_DESC_STR_HEADER(len); + + return desc_str; +} diff --git a/ports/nrf/main.c b/ports/nrf/main.c index e82cfcf58dd56..ce8512aee34ad 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -70,6 +70,10 @@ #include "softpwm.h" #endif +#if MICROPY_HW_USB_CDC +#include "usb_cdc.h" +#endif + void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { @@ -121,6 +125,7 @@ int main(int argc, char **argv) { readline_init0(); + #if MICROPY_PY_MACHINE_HW_SPI spi_init0(); #endif @@ -149,7 +154,7 @@ int main(int argc, char **argv) { uart_init0(); #endif -#if (MICROPY_PY_BLE_NUS == 0) +#if (MICROPY_PY_BLE_NUS == 0) && (MICROPY_HW_USB_CDC == 0) { mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(0), @@ -231,6 +236,10 @@ led_state(1, 0); pyexec_file_if_exists("main.py"); #endif +#if MICROPY_HW_USB_CDC + usb_cdc_init(); +#endif + for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index bf89697083c07..b915c23e47a97 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -62,7 +62,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { } return ret; } +#endif +#if !MICROPY_PY_BLE_NUS && !MICROPY_HW_USB_CDC int mp_hal_stdin_rx_chr(void) { for (;;) { if (MP_STATE_PORT(board_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(board_stdio_uart))) { diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index 99085a2fe86ba..505ecf57bd1d1 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -47,6 +47,14 @@ #define GPIO_COUNT 2 #endif +#if defined(NRF52840) +// for tinyusb +//#define NRFX_IRQ_IS_ENABLED 1 +#define NRFX_POWER_ENABLED 1 +#define NRFX_POWER_CONFIG_IRQ_PRIORITY 2 +#define NRFX_SYSTICK_ENABLED 1 +#endif + #define NRFX_GPIOTE_ENABLED 1 #define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1 #if NRF51 diff --git a/ports/nrf/nrfx_glue.h b/ports/nrf/nrfx_glue.h index 316e02df1d54c..ffd2cff736e66 100644 --- a/ports/nrf/nrfx_glue.h +++ b/ports/nrf/nrfx_glue.h @@ -138,4 +138,6 @@ #endif // !BLUETOOTH_SD +#define NRFX_IRQ_IS_ENABLED(irq_number) (0 != (NVIC->ISER[irq_number / 32] & (1UL << (irq_number % 32)))) + #endif // NRFX_GLUE_H From 01a3110e363bbde22b3f26191ac2cececf1afdbc Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Wed, 9 Oct 2019 20:25:12 +0200 Subject: [PATCH 0546/1299] nrf/boards: Add support for pca10059. Add support for pca10059 with REPL over tinyusb USB CDC. The board also includes a board specific module that will recover UICR->REGOUT0 in case this has been erased. This initial support does not preserve any existing bootloader on the pca10090 in case this was present, and expects to use all available flash on the device. --- ports/nrf/README.md | 2 + .../boards/pca10059/modules/boardmodules.h | 34 +++++++++ .../boards/pca10059/modules/boardmodules.mk | 11 +++ .../pca10059/modules/recover_uicr_regout0.c | 61 ++++++++++++++++ ports/nrf/boards/pca10059/mpconfigboard.h | 73 +++++++++++++++++++ ports/nrf/boards/pca10059/mpconfigboard.mk | 7 ++ ports/nrf/boards/pca10059/pins.csv | 31 ++++++++ 7 files changed, 219 insertions(+) create mode 100644 ports/nrf/boards/pca10059/modules/boardmodules.h create mode 100644 ports/nrf/boards/pca10059/modules/boardmodules.mk create mode 100644 ports/nrf/boards/pca10059/modules/recover_uicr_regout0.c create mode 100644 ports/nrf/boards/pca10059/mpconfigboard.h create mode 100644 ports/nrf/boards/pca10059/mpconfigboard.mk create mode 100644 ports/nrf/boards/pca10059/pins.csv diff --git a/ports/nrf/README.md b/ports/nrf/README.md index 49642f00e9e61..834e2ea291a53 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -39,6 +39,7 @@ This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. * [uBlox EVK-NINA-B1](https://www.u-blox.com/en/product/evk-nina-b1) * nRF52840 * [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK) + * [PCA10059](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) * [Particle Xenon](https://docs.particle.io/xenon/) ## Compile and Flash @@ -129,6 +130,7 @@ idk_blyst_nano | s132 | Peripheral and Central | [IDAP] blueio_tag_evim | s132 | Peripheral and Central | [IDAP](#idap-midap-link-targets) evk_nina_b1 | s132 | Peripheral and Central | [Segger](#segger-targets) pca10056 | s140 | Peripheral and Central | [Segger](#segger-targets) +pca10059 | s140 | Peripheral and Central | Manual, SWDIO and SWCLK solder points on the sides. particle_xenon | s140 | Peripheral and Central | [Black Magic Probe](#black-magic-probe-targets) ## IDAP-M/IDAP-Link Targets diff --git a/ports/nrf/boards/pca10059/modules/boardmodules.h b/ports/nrf/boards/pca10059/modules/boardmodules.h new file mode 100644 index 0000000000000..1d70ec91618df --- /dev/null +++ b/ports/nrf/boards/pca10059/modules/boardmodules.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_NRF_BOARD_PCA10059_BOARD_MODULES_H +#define MICROPY_INCLUDED_NRF_BOARD_PCA10059_BOARD_MODULES_H + +#define BOARD_MODULES + +void board_modules_init0(void); + +#endif // MICROPY_INCLUDED_NRF_BOARD_PCA10059_BOARD_MODULES_H diff --git a/ports/nrf/boards/pca10059/modules/boardmodules.mk b/ports/nrf/boards/pca10059/modules/boardmodules.mk new file mode 100644 index 0000000000000..413790fbea7d5 --- /dev/null +++ b/ports/nrf/boards/pca10059/modules/boardmodules.mk @@ -0,0 +1,11 @@ +BOARD_PCA10059_DIR = boards/pca10059/modules + +INC += -I./$(BOARD_PCA10059_DIR) +CFLAGS += -DBOARD_SPECIFIC_MODULES + +SRC_BOARD_MODULES = $(addprefix $(BOARD_PCA10059_DIR)/,\ + recover_uicr_regout0.c \ + ) + +OBJ += $(addprefix $(BUILD)/, $(SRC_BOARD_MODULES:.c=.o)) + diff --git a/ports/nrf/boards/pca10059/modules/recover_uicr_regout0.c b/ports/nrf/boards/pca10059/modules/recover_uicr_regout0.c new file mode 100644 index 0000000000000..8ae5e218aaac8 --- /dev/null +++ b/ports/nrf/boards/pca10059/modules/recover_uicr_regout0.c @@ -0,0 +1,61 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "nrf.h" +#include "nrf52840_bitfields.h" + +bool uicr_REGOUT0_erased() { + if (NRF_UICR->REGOUT0 == 0xFFFFFFFFUL) { + return true; + } + return false; +} + +void board_modules_init0(void) +{ + if (uicr_REGOUT0_erased()) { + + // Wait for pending NVMC operations to finish. + while (NRF_NVMC->READY != NVMC_READY_READY_Ready); + + // Enable write mode in NVMC. + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; + while (NRF_NVMC->READY != NVMC_READY_READY_Ready); + + // Write 3v3 value to UICR->REGOUT0. + NRF_UICR->REGOUT0 = (UICR_REGOUT0_VOUT_3V3 & UICR_REGOUT0_VOUT_Msk) << UICR_REGOUT0_VOUT_Pos; + while (NRF_NVMC->READY != NVMC_READY_READY_Ready); + + // Enable read mode in NVMC. + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; + while (NRF_NVMC->READY != NVMC_READY_READY_Ready); + + // Reset to apply the update. + NVIC_SystemReset(); + } +} diff --git a/ports/nrf/boards/pca10059/mpconfigboard.h b/ports/nrf/boards/pca10059/mpconfigboard.h new file mode 100644 index 0000000000000..08fda1bb29d6b --- /dev/null +++ b/ports/nrf/boards/pca10059/mpconfigboard.h @@ -0,0 +1,73 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Glenn Ruben Bakke + * + * 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. + */ + +#define MICROPY_HW_BOARD_NAME "PCA10059" +#define MICROPY_HW_MCU_NAME "NRF52840" +#define MICROPY_PY_SYS_PLATFORM "nrf52840-Dongle" + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_PWM (1) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (1) +#define MICROPY_PY_MACHINE_RTCOUNTER (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (1) +#define MICROPY_PY_MACHINE_TEMP (1) +#define MICROPY_PY_RANDOM_HW_RNG (1) + +#define MICROPY_HW_USB_CDC (1) + +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_LED_COUNT (4) +#define MICROPY_HW_LED_PULLUP (1) + +#define MICROPY_HW_LED1 (6) // LED1 GREEN +#define MICROPY_HW_LED2 (8) // LED2 RED (RGB) +#define MICROPY_HW_LED3 (41) // LED2 GREEN (RGB) +#define MICROPY_HW_LED4 (12) // LED2 BLUE (RGB) + +// UART config +#define MICROPY_HW_UART1_RX (13) +#define MICROPY_HW_UART1_TX (15) +#define MICROPY_HW_UART1_CTS (17) +#define MICROPY_HW_UART1_RTS (20) +#define MICROPY_HW_UART1_HWFC (1) + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" + +#define MICROPY_HW_SPI0_SCK (22) +#define MICROPY_HW_SPI0_MOSI (32) +#define MICROPY_HW_SPI0_MISO (24) + +#define MICROPY_HW_PWM0_NAME "PWM0" +#define MICROPY_HW_PWM1_NAME "PWM1" +#define MICROPY_HW_PWM2_NAME "PWM2" +#if 0 +#define MICROPY_HW_PWM3_NAME "PWM3" +#endif + +#define HELP_TEXT_BOARD_LED "1,2,3,4" diff --git a/ports/nrf/boards/pca10059/mpconfigboard.mk b/ports/nrf/boards/pca10059/mpconfigboard.mk new file mode 100644 index 0000000000000..ca555d3932aa4 --- /dev/null +++ b/ports/nrf/boards/pca10059/mpconfigboard.mk @@ -0,0 +1,7 @@ +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52840 +SOFTDEV_VERSION = 6.1.1 +LD_FILES += boards/nrf52840_1M_256k.ld + +NRF_DEFINES += -DNRF52840_XXAA diff --git a/ports/nrf/boards/pca10059/pins.csv b/ports/nrf/boards/pca10059/pins.csv new file mode 100644 index 0000000000000..9d142b9f12168 --- /dev/null +++ b/ports/nrf/boards/pca10059/pins.csv @@ -0,0 +1,31 @@ +P2,P2,ADC0_IN0 +P4,P4,ADC0_IN2 +LED1_GREEN,P6 +LED2_RED,P8 +P9,P9 +P10,P10 +P11,P11 +LED2_BLUE,P12 +UART1_RX,P13 +P14,P14 +UART1_TX,P15 +P16,P16 +UART1_CTS,P17 +SWITCH2_NRESET,P18 +UART1_RTS,P20 +SPI0_SCK,P22,P22 +SPI0_MISO,P24 +P26,P26 +P29,P29,ADC0_IN5 +P31,P31,ADC0_IN7 +SPI0_MOSI,P32 +P33,P33 +P34,P34 +P36,P36 +SWITCH1,P38,P38 +P39,P39 +LED2_GREEN,P41 +P42,P42 +P43,P43 +P45,P45 +P47,P47 From 82fe6b0526ad8c10e923174a45063f93f312d681 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Thu, 26 Sep 2019 22:25:16 +0200 Subject: [PATCH 0547/1299] nrf: Add nrf9160 base support. This patch add basic building blocks for nrf9P60. It also includes a secure bootloader which forwards all possible peripherals that are user selectable to become non-secure. After configuring Flash, RAM and peripherals the secure bootloader will jump to the non-secure domain where MicroPython is placed. The minimum size of a secure boot has to be a flash block of 32Kb, hence why the linker scripts are offsetting the main application this much. The RAM offset is set to 128K, to allow for later integration of Nordic Semiconductor's BSD socket library which reserves the range 0x20010000 - 0x2001FFFF. --- ports/nrf/Makefile | 59 +++- ports/nrf/boards/nrf9160_1M_256k.ld | 13 + ports/nrf/boards/nrf9160_1M_256k_secure.ld | 6 + ports/nrf/boards/nrf91_prefix.c | 29 ++ ports/nrf/device/startup_nrf9160.c | 270 ++++++++++++++++++ ports/nrf/drivers/flash.h | 4 + ports/nrf/drivers/secureboot/secureboot.mk | 55 ++++ .../nrf/drivers/secureboot/secureboot_main.c | 194 +++++++++++++ ports/nrf/main.c | 3 +- ports/nrf/modules/machine/modmachine.c | 2 + ports/nrf/mphalport.c | 3 +- ports/nrf/nrf91_af.csv | 32 +++ ports/nrf/nrfx_config.h | 109 ++++++- ports/nrf/pin_defs_nrf5.h | 5 + 14 files changed, 770 insertions(+), 14 deletions(-) create mode 100644 ports/nrf/boards/nrf9160_1M_256k.ld create mode 100644 ports/nrf/boards/nrf9160_1M_256k_secure.ld create mode 100644 ports/nrf/boards/nrf91_prefix.c create mode 100644 ports/nrf/device/startup_nrf9160.c create mode 100644 ports/nrf/drivers/secureboot/secureboot.mk create mode 100644 ports/nrf/drivers/secureboot/secureboot_main.c create mode 100644 ports/nrf/nrf91_af.csv diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 46dd8c8d71be2..a8bd95cc6df85 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -82,6 +82,9 @@ else ifeq ($(MCU_SUB_VARIANT),nrf52832) else ifeq ($(MCU_SUB_VARIANT),nrf52840) SYSTEM_C_SRC += $(addprefix lib/nrfx/mdk/, system_nrf52840.c) # Do not pass MCU_VARIANT_UPPER flag, as NRF52 defines NRF52832 only. +else ifeq ($(MCU_SUB_VARIANT),nrf9160) + SYSTEM_C_SRC += $(addprefix lib/nrfx/mdk/, system_nrf9160.c) + NRF_DEFINES += -D$(MCU_VARIANT_UPPER) endif NRF_DEFINES += -D$(MCU_SUB_VARIANT_UPPER) @@ -89,6 +92,8 @@ NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion +CFLAGS_MCU_m33 = $(CFLAGS_CORTEX_M) -mcpu=cortex-m33 -march=armv8-m.main+dsp -mcmse -mfpu=fpv5-sp-d16 -mfloat-abi=hard + CFLAGS_MCU_m4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS_MCU_m0 = $(CFLAGS_CORTEX_M) -fshort-enums -mtune=cortex-m0 -mcpu=cortex-m0 -mfloat-abi=soft -fno-builtin @@ -125,10 +130,31 @@ endif LIBS = \ ifeq ($(MCU_VARIANT), nrf52) -LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) -LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc +SRC_LIB += $(addprefix lib/,\ + libm/math.c \ + libm/fmodf.c \ + libm/nearbyintf.c \ + libm/ef_sqrt.c \ + libm/kf_rem_pio2.c \ + libm/kf_sin.c \ + libm/kf_cos.c \ + libm/kf_tan.c \ + libm/ef_rem_pio2.c \ + libm/sf_sin.c \ + libm/sf_cos.c \ + libm/sf_tan.c \ + libm/sf_frexp.c \ + libm/sf_modf.c \ + libm/sf_ldexp.c \ + libm/asinfacosf.c \ + libm/atanf.c \ + libm/atan2f.c \ + ) + +endif +ifeq ($(MCU_VARIANT), nrf91) SRC_LIB += $(addprefix lib/,\ libm/math.c \ @@ -149,7 +175,14 @@ SRC_LIB += $(addprefix lib/,\ libm/asinfacosf.c \ libm/atanf.c \ libm/atan2f.c \ - ) + ) + +SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ + nrfx_uarte.c \ + nrfx_twim.c \ + ) + +include drivers/secureboot/secureboot.mk endif @@ -271,13 +304,16 @@ FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) endif +LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc + OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SYSTEM_C_SRC:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(BUILD)/pins_gen.o $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os @@ -285,7 +321,11 @@ $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os .PHONY: all flash deploy sd binary hex +ifeq ($(MCU_VARIANT), nrf91) +all: binary hex secureboot +else all: binary hex +endif OUTPUT_FILENAME = firmware @@ -305,10 +345,21 @@ FLASHER ?= ifeq ($(FLASHER),) +ifeq ($(MCU_VARIANT), nrf91) + +deploy: $(BUILD)/$(OUTPUT_FILENAME).hex $(BUILD)/secureboot.hex + nrfjprog --program $(BUILD)/secureboot.hex --sectorerase -f $(MCU_VARIANT) + nrfjprog --program $(BUILD)/$(OUTPUT_FILENAME).hex --sectorerase -f $(MCU_VARIANT) + nrfjprog --reset -f $(MCU_VARIANT) + +else + deploy: $(BUILD)/$(OUTPUT_FILENAME).hex nrfjprog --program $< --sectorerase -f $(MCU_VARIANT) nrfjprog --reset -f $(MCU_VARIANT) +endif + sd: $(BUILD)/$(OUTPUT_FILENAME).hex nrfjprog --eraseall -f $(MCU_VARIANT) nrfjprog --program $(SOFTDEV_HEX) -f $(MCU_VARIANT) diff --git a/ports/nrf/boards/nrf9160_1M_256k.ld b/ports/nrf/boards/nrf9160_1M_256k.ld new file mode 100644 index 0000000000000..6347095a899ce --- /dev/null +++ b/ports/nrf/boards/nrf9160_1M_256k.ld @@ -0,0 +1,13 @@ +/* + GNU linker script for NRF9160 NS +*/ + +_flash_size = 1M; +_ram_size = 256K; +_sd_size = 0x00008000; +_sd_ram = 0x00020000; +_fs_size = 80K; + +/* produce a link error if there is not this amount of RAM for these sections */ +_stack_size = 32K; +_minimum_heap_size = 64K; diff --git a/ports/nrf/boards/nrf9160_1M_256k_secure.ld b/ports/nrf/boards/nrf9160_1M_256k_secure.ld new file mode 100644 index 0000000000000..79db18ab226ca --- /dev/null +++ b/ports/nrf/boards/nrf9160_1M_256k_secure.ld @@ -0,0 +1,6 @@ +/* Specify the memory areas */ +MEMORY +{ + FLASH_TEXT (rx) : ORIGIN = 0x00000000, LENGTH = 32K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K +} diff --git a/ports/nrf/boards/nrf91_prefix.c b/ports/nrf/boards/nrf91_prefix.c new file mode 100644 index 0000000000000..d8bb0fc70ba87 --- /dev/null +++ b/ports/nrf/boards/nrf91_prefix.c @@ -0,0 +1,29 @@ +// nrf91_prefix.c becomes the initial portion of the generated pins file. + +#include + +#include "py/obj.h" +#include "py/mphal.h" +#include "pin.h" + +#define AF(af_idx, af_fn, af_unit, af_type, af_ptr) \ +{ \ + { &pin_af_type }, \ + .name = MP_QSTR_AF ## af_idx ## _ ## af_fn ## af_unit, \ + .idx = (af_idx), \ + .fn = AF_FN_ ## af_fn, \ + .unit = (af_unit), \ + .type = AF_PIN_TYPE_ ## af_fn ## _ ## af_type, \ + .af_fn = (af_ptr) \ +} + +#define PIN(p_pin, p_af, p_adc_num, p_adc_channel) \ +{ \ + { &pin_type }, \ + .name = MP_QSTR_P ## p_pin, \ + .pin = (p_pin), \ + .num_af = (sizeof(p_af) / sizeof(pin_af_obj_t)), \ + .af = p_af, \ + .adc_num = p_adc_num, \ + .adc_channel = p_adc_channel, \ +} diff --git a/ports/nrf/device/startup_nrf9160.c b/ports/nrf/device/startup_nrf9160.c new file mode 100644 index 0000000000000..5a32ddff32a08 --- /dev/null +++ b/ports/nrf/device/startup_nrf9160.c @@ -0,0 +1,270 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Glenn Ruben Bakke + * + * 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 + +extern uint32_t _estack; +extern uint32_t _sidata; +extern uint32_t _sdata; +extern uint32_t _edata; +extern uint32_t _sbss; +extern uint32_t _ebss; + +typedef void (*func)(void); + +extern void _start(void) __attribute__((noreturn)); +extern void SystemInit(void); + +void Default_Handler(void) { while (1); } + +void Reserved_Handler1(void) { while (1); } +void Reserved_Handler2(void) { while (1); } +void Reserved_Handler3(void) { while (1); } +void Reserved_Handler4(void) { while (1); } +void Reserved_Handler5(void) { while (1); } +void Reserved_Handler6(void) { while (1); } +void Reserved_Handler7(void) { while (1); } +void Reserved_Handler8(void) { while (1); } +void Reserved_Handler9(void) { while (1); } +void Reserved_Handler10(void) { while (1); } +void Reserved_Handler11(void) { while (1); } +void Reserved_Handler12(void) { while (1); } +void Reserved_Handler13(void) { while (1); } +void Reserved_Handler14(void) { while (1); } +void Reserved_Handler15(void) { while (1); } +void Reserved_Handler16(void) { while (1); } +void Reserved_Handler17(void) { while (1); } +void Reserved_Handler18(void) { while (1); } +void Reserved_Handler19(void) { while (1); } +void Reserved_Handler20(void) { while (1); } +void Reserved_Handler21(void) { while (1); } +void Reserved_Handler22(void) { while (1); } +void Reserved_Handler23(void) { while (1); } +void Reserved_Handler24(void) { while (1); } +void Reserved_Handler25(void) { while (1); } +void Reserved_Handler26(void) { while (1); } +void Reserved_Handler27(void) { while (1); } +void Reserved_Handler28(void) { while (1); } +void Reserved_Handler29(void) { while (1); } +void Reserved_Handler30(void) { while (1); } +void Reserved_Handler31(void) { while (1); } +void Reserved_Handler32(void) { while (1); } +void Reserved_Handler33(void) { while (1); } +void Reserved_Handler34(void) { while (1); } +void Reserved_Handler35(void) { while (1); } +void Reserved_Handler36(void) { while (1); } +void Reserved_Handler37(void) { while (1); } +void Reserved_Handler38(void) { while (1); } + +void Default_NMI_Handler (void) { while (1); } +void Default_HardFault_Handler (void) { while (1); } +void Default_MemoryManagement_Handler (void) { while (1); } +void Default_BusFault_Handler (void) { while (1); } +void Default_UsageFault_Handler (void) { while (1); } +void Default_SecureFault_Handler (void) { while (1); } +void Default_SVC_Handler (void) { while (1); } +void Default_DebugMon_Handler (void) { while (1); } +void Default_PendSV_Handler (void) { while (1); } +void Default_SysTick_Handler (void) { while (1); } + +void Default_SPU_IRQHandler (void) { while (1); } +void Default_CLOCK_POWER_IRQHandler (void) { while (1); } +void Default_UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler (void) { while (1); } +void Default_UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler (void) { while (1); } +void Default_UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler (void) { while (1); } +void Default_UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler (void) { while (1); } +void Default_GPIOTE0_IRQHandler (void) { while (1); } +void Default_SAADC_IRQHandler (void) { while (1); } +void Default_TIMER0_IRQHandler (void) { while (1); } +void Default_TIMER1_IRQHandler (void) { while (1); } +void Default_TIMER2_IRQHandler (void) { while (1); } +void Default_RTC0_IRQHandler (void) { while (1); } +void Default_RTC1_IRQHandler (void) { while (1); } +void Default_WDT_IRQHandler (void) { while (1); } +void Default_EGU0_IRQHandler (void) { while (1); } +void Default_EGU1_IRQHandler (void) { while (1); } +void Default_EGU2_IRQHandler (void) { while (1); } +void Default_EGU3_IRQHandler (void) { while (1); } +void Default_EGU4_IRQHandler (void) { while (1); } +void Default_EGU5_IRQHandler (void) { while (1); } +void Default_PWM0_IRQHandler (void) { while (1); } +void Default_PWM1_IRQHandler (void) { while (1); } +void Default_PWM2_IRQHandler (void) { while (1); } +void Default_PWM3_IRQHandler (void) { while (1); } +void Default_PDM_IRQHandler (void) { while (1); } +void Default_I2S_IRQHandler (void) { while (1); } +void Default_IPC_IRQHandler (void) { while (1); } +void Default_FPU_IRQHandler (void) { while (1); } +void Default_GPIOTE1_IRQHandler (void) { while (1); } +void Default_KMU_IRQHandler (void) { while (1); } +void Default_CRYPTOCELL_IRQHandler (void) { while (1); } + +void Reset_Handler(void) { + uint32_t * p_src = &_sidata; + uint32_t * p_dest = &_sdata; + + while (p_dest < &_edata) { + *p_dest++ = *p_src++; + } + + uint32_t * p_bss = &_sbss; + uint32_t * p_bss_end = &_ebss; + while (p_bss < p_bss_end) { + *p_bss++ = 0ul; + } + + SystemInit(); + _start(); +} + +void NMI_Handler (void) __attribute__ ((weak, alias("Default_Handler"))); +void HardFault_Handler (void) __attribute__ ((weak, alias("Default_HardFault_Handler"))); +void MemoryManagement_Handler (void) __attribute__ ((weak, alias("Default_MemoryManagement_Handler"))); +void BusFault_Handler (void) __attribute__ ((weak, alias("Default_BusFault_Handler"))); +void UsageFault_Handler (void) __attribute__ ((weak, alias("Default_UsageFault_Handler"))); +void SecureFault_Handler (void) __attribute__ ((weak, alias("Default_SecureFault_Handler"))); +void SVC_Handler (void) __attribute__ ((weak, alias("Default_SVC_Handler"))); +void DebugMon_Handler (void) __attribute__ ((weak, alias("Default_DebugMon_Handler"))); +void PendSV_Handler (void) __attribute__ ((weak, alias("Default_PendSV_Handler"))); +void SysTick_Handler (void) __attribute__ ((weak, alias("Default_SysTick_Handler"))); + +void SPU_IRQHandler (void) __attribute__ ((weak, alias("Default_SPU_IRQHandler"))); +void CLOCK_POWER_IRQHandler (void) __attribute__ ((weak, alias("Default_CLOCK_POWER_IRQHandler"))); +void UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler"))); +void UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler"))); +void UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler"))); +void UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler (void) __attribute__ ((weak, alias("Default_UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler"))); +void GPIOTE0_IRQHandler (void) __attribute__ ((weak, alias("Default_GPIOTE0_IRQHandler"))); +void SAADC_IRQHandler (void) __attribute__ ((weak, alias("Default_SAADC_IRQHandler"))); +void TIMER0_IRQHandler (void) __attribute__ ((weak, alias("Default_TIMER0_IRQHandler"))); +void TIMER1_IRQHandler (void) __attribute__ ((weak, alias("Default_TIMER1_IRQHandler"))); +void TIMER2_IRQHandler (void) __attribute__ ((weak, alias("Default_TIMER2_IRQHandler"))); +void RTC0_IRQHandler (void) __attribute__ ((weak, alias("Default_RTC0_IRQHandler"))); +void RTC1_IRQHandler (void) __attribute__ ((weak, alias("Default_RTC1_IRQHandler"))); +void WDT_IRQHandler (void) __attribute__ ((weak, alias("Default_WDT_IRQHandler"))); +void EGU0_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU0_IRQHandler"))); +void EGU1_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU1_IRQHandler"))); +void EGU2_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU2_IRQHandler"))); +void EGU3_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU3_IRQHandler"))); +void EGU4_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU4_IRQHandler"))); +void EGU5_IRQHandler (void) __attribute__ ((weak, alias("Default_EGU5_IRQHandler"))); +void PWM0_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM0_IRQHandler"))); +void PWM1_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM1_IRQHandler"))); +void PWM2_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM2_IRQHandler"))); +void PWM3_IRQHandler (void) __attribute__ ((weak, alias("Default_PWM3_IRQHandler"))); +void PDM_IRQHandler (void) __attribute__ ((weak, alias("Default_PDM_IRQHandler"))); +void I2S_IRQHandler (void) __attribute__ ((weak, alias("Default_I2S_IRQHandler"))); +void IPC_IRQHandler (void) __attribute__ ((weak, alias("Default_IPC_IRQHandler"))); +void FPU_IRQHandler (void) __attribute__ ((weak, alias("Default_FPU_IRQHandler"))); +void GPIOTE1_IRQHandler (void) __attribute__ ((weak, alias("Default_GPIOTE1_IRQHandler"))); +void KMU_IRQHandler (void) __attribute__ ((weak, alias("Default_KMU_IRQHandler"))); +void CRYPTOCELL_IRQHandler (void) __attribute__ ((weak, alias("Default_CRYPTOCELL_IRQHandler"))); + +const func __Vectors[] __attribute__ ((section(".isr_vector"),used)) = { + (func)&_estack, + Reset_Handler, + NMI_Handler, + HardFault_Handler, + MemoryManagement_Handler, + BusFault_Handler, + UsageFault_Handler, + SecureFault_Handler, + Reserved_Handler1, + Reserved_Handler2, + Reserved_Handler3, + SVC_Handler, + DebugMon_Handler, + Reserved_Handler4, + PendSV_Handler, + SysTick_Handler, + + /* External Interrupts */ + Reserved_Handler5, + Reserved_Handler6, + Reserved_Handler7, + SPU_IRQHandler, + Reserved_Handler8, + CLOCK_POWER_IRQHandler, + Reserved_Handler9, + Reserved_Handler10, + UARTE0_SPIM0_SPIS0_TWIM0_TWIS0_IRQHandler, + UARTE1_SPIM1_SPIS1_TWIM1_TWIS1_IRQHandler, + UARTE2_SPIM2_SPIS2_TWIM2_TWIS2_IRQHandler, + UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQHandler, + Reserved_Handler11, + GPIOTE0_IRQHandler, + SAADC_IRQHandler, + TIMER0_IRQHandler, + TIMER1_IRQHandler, + TIMER2_IRQHandler, + Reserved_Handler12, + Reserved_Handler13, + RTC0_IRQHandler, + RTC1_IRQHandler, + Reserved_Handler14, + Reserved_Handler15, + WDT_IRQHandler, + Reserved_Handler16, + Reserved_Handler17, + EGU0_IRQHandler, + EGU1_IRQHandler, + EGU2_IRQHandler, + EGU3_IRQHandler, + EGU4_IRQHandler, + EGU5_IRQHandler, + PWM0_IRQHandler, + PWM1_IRQHandler, + PWM2_IRQHandler, + PWM3_IRQHandler, + Reserved_Handler18, + PDM_IRQHandler, + Reserved_Handler19, + I2S_IRQHandler, + Reserved_Handler20, + IPC_IRQHandler, + Reserved_Handler21, + FPU_IRQHandler, + Reserved_Handler22, + Reserved_Handler23, + Reserved_Handler24, + Reserved_Handler25, + GPIOTE1_IRQHandler, + Reserved_Handler26, + Reserved_Handler27, + Reserved_Handler28, + Reserved_Handler29, + Reserved_Handler30, + Reserved_Handler31, + Reserved_Handler32, + KMU_IRQHandler, + Reserved_Handler33, + Reserved_Handler34, + Reserved_Handler35, + Reserved_Handler36, + Reserved_Handler37, + Reserved_Handler38, + CRYPTOCELL_IRQHandler, +}; diff --git a/ports/nrf/drivers/flash.h b/ports/nrf/drivers/flash.h index 3dd5d06dd4e75..ed53afd81bff6 100644 --- a/ports/nrf/drivers/flash.h +++ b/ports/nrf/drivers/flash.h @@ -34,6 +34,10 @@ #elif defined(NRF52_SERIES) #define FLASH_PAGESIZE (4096) + +#elif defined(NRF91_SERIES) +#define FLASH_PAGESIZE (4096) + #else #error Unknown chip #endif diff --git a/ports/nrf/drivers/secureboot/secureboot.mk b/ports/nrf/drivers/secureboot/secureboot.mk new file mode 100644 index 0000000000000..89833cb6def16 --- /dev/null +++ b/ports/nrf/drivers/secureboot/secureboot.mk @@ -0,0 +1,55 @@ +DRIVERS_SECUREBOOT_DIR = drivers/secureboot + +SRC_SECUREBOOT += $(addprefix $(DRIVERS_SECUREBOOT_DIR)/,\ + secureboot_main.c \ + ) + +SRC_SECUREBOOT += $(addprefix device/,\ + startup_nrf9160.c \ + ) + +SRC_SECUREBOOT += $(addprefix $(TOP)/lib/nrfx/mdk/,\ + system_nrf9160.c \ + ) + +.PHONY: secureboot clean + +INC_SECUREBOOT += -I./../../lib/nrfx/mdk +INC_SECUREBOOT += -I./../../lib/cmsis/inc + +MCU_SERIES = m33 + +CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion + +CFLAGS_MCU_m33 = $(CFLAGS_CORTEX_M) -mcpu=cortex-m33 -march=armv8-m.main+dsp -mcmse -mfpu=fpv5-sp-d16 -mfloat-abi=hard + + +CFLAGS_SECUREBOOT += -DNRF9160_XXAA +CFLAGS_SECUREBOOT += $(CFLAGS_MCU_$(MCU_SERIES)) +CFLAGS_SECUREBOOT += -Wall -Werror -g -ansi -std=c11 -nostdlib $(COPT) +CFLAGS_SECUREBOOT += -fno-strict-aliasing + +LD_FILES_SECUREBOOT += nrf9160_1M_256k_secure.ld common.ld + +LDFLAGS_SECUREBOOT = $(CFLAGS_SECUREBOOT) +LDFLAGS_SECUREBOOT += -Xlinker -Map=$(@:.elf=.map) +LDFLAGS_SECUREBOOT += -mthumb -mabi=aapcs $(addprefix -T,$(LD_FILES_SECUREBOOT)) -L ./boards + +CC = arm-none-eabi-gcc +SIZE = arm-none-eabi-size +OBJCOPY = arm-none-eabi-objcopy + +LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS_SECUREBOOT) -print-libgcc-file-name) +LIBC_FILE_NAME = $(shell $(CC) $(CFLAGS_SECUREBOOT) -print-file-name=libc.a) +LIBS_SECUREBOOT += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc +LIBS_SECUREBOOT += -L $(dir $(LIBC_FILE_NAME)) -lc + +$(BUILD)/secureboot.elf: + $(Q)$(CC) $(LDFLAGS_SECUREBOOT) $(SRC_SECUREBOOT) $(INC_SECUREBOOT) -O3 -o $@ $(LIBS_SECUREBOOT) + $(SIZE) $@ + +$(BUILD)/secureboot.hex: $(BUILD)/secureboot.elf + $(OBJCOPY) -O ihex $< $@ + +secureboot: $(BUILD)/secureboot.hex + @echo "Secure boot" diff --git a/ports/nrf/drivers/secureboot/secureboot_main.c b/ports/nrf/drivers/secureboot/secureboot_main.c new file mode 100644 index 0000000000000..748e080a24fe2 --- /dev/null +++ b/ports/nrf/drivers/secureboot/secureboot_main.c @@ -0,0 +1,194 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +// Secure flash 32K. +#define SECURE_32K_FLASH_PAGE_START (0) +#define SECURE_32K_FLASH_PAGE_END (0) + +// Non-secure flash 992K. +#define NONSECURE_32K_FLASH_PAGE_START (1) +#define NONSECURE_32K_FLASH_PAGE_END (31) + +// Secure RAM 64K. +#define SECURE_8K_RAM_BLOCK_START (0) +#define SECURE_8K_RAM_BLOCK_END (7) + +// Non-secure RAM 128K + 64K BSD lib. +#define NONSECURE_8K_RAM_BLOCK_START (8) +#define NONSECURE_8K_RAM_BLOCK_END (31) + +#define PERIPHERAL_ID_GET(base_addr) (((uint32_t)(base_addr) >> 12) & 0xFF) + +#if !defined(__ARM_FEATURE_CMSE) + #pragma warning "CMSE not enabled" +#endif + +static void configure_flash(void) { + for (uint8_t i = SECURE_32K_FLASH_PAGE_START; i <= SECURE_32K_FLASH_PAGE_END; i++) { + uint32_t perm = 0; + perm |= (SPU_FLASHREGION_PERM_EXECUTE_Enable << SPU_FLASHREGION_PERM_EXECUTE_Pos); + perm |= (SPU_FLASHREGION_PERM_WRITE_Enable << SPU_FLASHREGION_PERM_WRITE_Pos); + perm |= (SPU_FLASHREGION_PERM_READ_Enable << SPU_FLASHREGION_PERM_READ_Pos); + perm |= (SPU_FLASHREGION_PERM_LOCK_Locked << SPU_FLASHREGION_PERM_LOCK_Pos); + perm |= (SPU_FLASHREGION_PERM_SECATTR_Secure << SPU_FLASHREGION_PERM_SECATTR_Pos); + NRF_SPU_S->FLASHREGION[i].PERM = perm; + } + + for (uint8_t i = NONSECURE_32K_FLASH_PAGE_START; i <= NONSECURE_32K_FLASH_PAGE_END; i++) { + uint32_t perm = 0; + perm |= (SPU_FLASHREGION_PERM_EXECUTE_Enable << SPU_FLASHREGION_PERM_EXECUTE_Pos); + perm |= (SPU_FLASHREGION_PERM_WRITE_Enable << SPU_FLASHREGION_PERM_WRITE_Pos); + perm |= (SPU_FLASHREGION_PERM_READ_Enable << SPU_FLASHREGION_PERM_READ_Pos); + perm |= (SPU_FLASHREGION_PERM_LOCK_Locked << SPU_FLASHREGION_PERM_LOCK_Pos); + perm |= (SPU_FLASHREGION_PERM_SECATTR_Non_Secure << SPU_FLASHREGION_PERM_SECATTR_Pos); + NRF_SPU_S->FLASHREGION[i].PERM = perm; + } +} + +static void configure_ram(void) { + for (uint8_t i = SECURE_8K_RAM_BLOCK_START; i <= SECURE_8K_RAM_BLOCK_END; i++) { + uint32_t perm = 0; + perm |= (SPU_RAMREGION_PERM_EXECUTE_Enable << SPU_RAMREGION_PERM_EXECUTE_Pos); + perm |= (SPU_RAMREGION_PERM_WRITE_Enable << SPU_RAMREGION_PERM_WRITE_Pos); + perm |= (SPU_RAMREGION_PERM_READ_Enable << SPU_RAMREGION_PERM_READ_Pos); + perm |= (SPU_RAMREGION_PERM_LOCK_Locked << SPU_RAMREGION_PERM_LOCK_Pos); + perm |= (SPU_RAMREGION_PERM_SECATTR_Secure << SPU_RAMREGION_PERM_SECATTR_Pos); + NRF_SPU_S->RAMREGION[i].PERM = perm; + } + + for (uint8_t i = NONSECURE_8K_RAM_BLOCK_START; i <= NONSECURE_8K_RAM_BLOCK_END; i++) { + uint32_t perm = 0; + perm |= (SPU_RAMREGION_PERM_EXECUTE_Enable << SPU_RAMREGION_PERM_EXECUTE_Pos); + perm |= (SPU_RAMREGION_PERM_WRITE_Enable << SPU_RAMREGION_PERM_WRITE_Pos); + perm |= (SPU_RAMREGION_PERM_READ_Enable << SPU_RAMREGION_PERM_READ_Pos); + perm |= (SPU_RAMREGION_PERM_LOCK_Locked << SPU_RAMREGION_PERM_LOCK_Pos); + perm |= (SPU_RAMREGION_PERM_SECATTR_Non_Secure << SPU_RAMREGION_PERM_SECATTR_Pos); + NRF_SPU_S->RAMREGION[i].PERM = perm; + } +} + +static void peripheral_setup(uint8_t peripheral_id) +{ + NVIC_DisableIRQ(peripheral_id); + uint32_t perm = 0; + perm |= (SPU_PERIPHID_PERM_PRESENT_IsPresent << SPU_PERIPHID_PERM_PRESENT_Pos); + perm |= (SPU_PERIPHID_PERM_SECATTR_NonSecure << SPU_PERIPHID_PERM_SECATTR_Pos); + perm |= (SPU_PERIPHID_PERM_LOCK_Locked << SPU_PERIPHID_PERM_LOCK_Pos); + NRF_SPU_S->PERIPHID[peripheral_id].PERM = perm; + + NVIC_SetTargetState(peripheral_id); +} + +static void configure_peripherals(void) +{ + NRF_SPU_S->GPIOPORT[0].PERM = 0; + peripheral_setup(PERIPHERAL_ID_GET(NRF_REGULATORS_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_CLOCK_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE0_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE1_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE2_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE3_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_SAADC_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER0_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER1_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER2_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_RTC0_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_RTC1_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_DPPIC_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_WDT_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU1_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU2_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU3_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU4_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU5_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM0_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM1_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM2_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM3_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_PDM_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_I2S_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_IPC_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_FPU_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_GPIOTE1_NS)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_NVMC_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_VMC_S)); + peripheral_setup(PERIPHERAL_ID_GET(NRF_P0_NS)); +} + +typedef void __attribute__((cmse_nonsecure_call)) nsfunc(void); + +static void jump_to_non_secure(void) +{ + TZ_SAU_Disable(); + SAU->CTRL |= SAU_CTRL_ALLNS_Msk; + + // Set NS vector table. + uint32_t * vtor_ns = (uint32_t *)0x8000; + SCB_NS->VTOR = (uint32_t)vtor_ns; + + // Allow for FPU to be used by NS. + SCB->NSACR |= (1UL << SCB_NSACR_CP10_Pos) | (1UL << SCB_NSACR_CP11_Pos); + + // Set stack pointers. + __TZ_set_MSP_NS(vtor_ns[0]); + __TZ_set_PSP_NS(0); + + uint32_t control_ns = __TZ_get_CONTROL_NS(); + control_ns &= ~(CONTROL_SPSEL_Msk | CONTROL_nPRIV_Msk); + __TZ_set_CONTROL_NS(control_ns); + + // Cast NS Reset_Handler to a non-secure function. + nsfunc *fp = (nsfunc *)vtor_ns[1]; + fp = (nsfunc *)((intptr_t)(fp) & ~1); + + if (cmse_is_nsfptr(fp)) { + __DSB(); + __ISB(); + + // Jump to Non-Secure function. + fp(); + } +} + +int main(void) { + configure_flash(); + configure_ram(); + configure_peripherals(); + + jump_to_non_secure(); + + while (1) { + ; + } + + return 0; +} + +void _start(void) {main();} + diff --git a/ports/nrf/main.c b/ports/nrf/main.c index ce8512aee34ad..26ac0ad6c9747 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -299,9 +299,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); #endif #endif + void HardFault_Handler(void) { -#if defined(NRF52_SERIES) +#if defined(NRF52_SERIES) || defined(NRF91_SERIES) static volatile uint32_t reg; static volatile uint32_t reg2; static volatile uint32_t bfar; diff --git a/ports/nrf/modules/machine/modmachine.c b/ports/nrf/modules/machine/modmachine.c index 841e136d0dbb1..1436495fcbcda 100644 --- a/ports/nrf/modules/machine/modmachine.c +++ b/ports/nrf/modules/machine/modmachine.c @@ -78,8 +78,10 @@ void machine_init(void) { reset_cause = PYB_RESET_LOCKUP; } else if (state & POWER_RESETREAS_OFF_Msk) { reset_cause = PYB_RESET_POWER_ON; +#if !defined(NRF9160_XXAA) } else if (state & POWER_RESETREAS_LPCOMP_Msk) { reset_cause = PYB_RESET_LPCOMP; +#endif } else if (state & POWER_RESETREAS_DIF_Msk) { reset_cause = PYB_RESET_DIF; #if defined(NRF52_SERIES) diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index b915c23e47a97..57d61b041d555 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -98,7 +98,6 @@ void mp_hal_delay_us(mp_uint_t us) if (us == 0) { return; } - register uint32_t delay __ASM ("r0") = us; __ASM volatile ( #ifdef NRF51 @@ -118,7 +117,7 @@ void mp_hal_delay_us(mp_uint_t us) " NOP\n" " NOP\n" " NOP\n" -#ifdef NRF52 +#if defined(NRF52) || defined(NRF9160_XXAA) " NOP\n" " NOP\n" " NOP\n" diff --git a/ports/nrf/nrf91_af.csv b/ports/nrf/nrf91_af.csv new file mode 100644 index 0000000000000..7d060f68fff36 --- /dev/null +++ b/ports/nrf/nrf91_af.csv @@ -0,0 +1,32 @@ +P0,P0 +P1,P1 +P2,P2 +P3,P3 +P4,P4 +P5,P5 +P6,P6 +P7,P7 +P8,P8 +P9,P9 +P10,P10 +P11,P11 +P12,P12 +P13,P13 +P14,P14 +P15,P15 +P16,P16 +P17,P17 +P18,P18 +P19,P19 +P20,P20 +P21,P21 +P22,P22 +P23,P23 +P24,P24 +P25,P25 +P26,P26 +P27,P27 +P28,P28 +P29,P29 +P30,P30 +P31,P31 diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index 505ecf57bd1d1..65b37e6aceaed 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -45,6 +45,8 @@ #define GPIO_COUNT 1 #elif NRF52840 || NRF52840_XXAA #define GPIO_COUNT 2 +#elif NRF9160_XXAA + #define GPIO_COUNT 1 #endif #if defined(NRF52840) @@ -63,12 +65,27 @@ #define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 6 #endif -#define NRFX_UART_ENABLED 1 -#define NRFX_UART0_ENABLED 1 +#if defined(NRF51) || defined(NRF52_SERIES) + #define NRFX_UART_ENABLED 1 + #define NRFX_UART0_ENABLED 1 + #define NRFX_UART1_ENABLED 1 +#else + #define NRFX_UARTE_ENABLED 1 + #define NRFX_UARTE0_ENABLED 1 + #define NRFX_UARTE1_ENABLED 1 + #define NRFX_UARTE2_ENABLED 1 + #define NRFX_UARTE3_ENABLED 1 +#endif -#define NRFX_TWI_ENABLED (MICROPY_PY_MACHINE_I2C) -#define NRFX_TWI0_ENABLED 1 -#define NRFX_TWI1_ENABLED 1 +#if defined(NRF51) || defined(NRF52_SERIES) + #define NRFX_TWI_ENABLED (MICROPY_PY_MACHINE_I2C) + #define NRFX_TWI0_ENABLED 1 + #define NRFX_TWI1_ENABLED 1 +#elif defined(NRF9160_XXAA) + #define NRFX_TWIM_ENABLED (MICROPY_PY_MACHINE_I2C) + #define NRFX_TWIM0_ENABLED 1 + #define NRFX_TWIM1_ENABLED 1 +#endif #if defined(NRF51) || defined(NRF52832) #define NRFX_SPI_ENABLED (MICROPY_PY_MACHINE_HW_SPI) @@ -84,6 +101,15 @@ #define NRFX_SPIM1_ENABLED 1 #define NRFX_SPIM2_ENABLED 1 #define NRFX_SPIM3_ENABLED (NRF52840) +#elif defined(NRF9160_XXAA) + #define NRFX_SPIM_ENABLED (MICROPY_PY_MACHINE_HW_SPI) + #define NRFX_SPIM0_ENABLED 1 + #define NRFX_SPIM1_ENABLED 1 + + // 0 NRF_GPIO_PIN_NOPULL + // 1 NRF_GPIO_PIN_PULLDOWN + // 3 NRF_GPIO_PIN_PULLUP + #define NRFX_SPIM_MISO_PULL_CFG 1 #endif // NRF51 // 0 NRF_GPIO_PIN_NOPULL @@ -101,8 +127,8 @@ #define NRFX_TIMER0_ENABLED 1 #define NRFX_TIMER1_ENABLED (!MICROPY_PY_MACHINE_SOFT_PWM) #define NRFX_TIMER2_ENABLED 1 -#define NRFX_TIMER3_ENABLED (!NRF51) -#define NRFX_TIMER4_ENABLED (!NRF51) +#define NRFX_TIMER3_ENABLED (!NRF51) && (!NRF9160_XXAA) +#define NRFX_TIMER4_ENABLED (!NRF51) && (!NRF9160_XXAA) #define NRFX_PWM_ENABLED (!NRF51) && MICROPY_PY_MACHINE_HW_PWM @@ -125,6 +151,10 @@ #define NRFX_PRS_BOX_0_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI0_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM0_ENABLED) #define NRFX_PRS_BOX_1_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI1_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM1_ENABLED) #define NRFX_PRS_BOX_2_ENABLED (NRFX_TWI_ENABLED && NRFX_TWI2_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM2_ENABLED) +#elif defined(NRF9160_XXAA) + #define NRFX_PRS_BOX_0_ENABLED (NRFX_TWIM_ENABLED && NRFX_TWIM0_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM0_ENABLED) + #define NRFX_PRS_BOX_1_ENABLED (NRFX_TWIM_ENABLED && NRFX_TWIM1_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM1_ENABLED) + #define NRFX_PRS_BOX_2_ENABLED (NRFX_TWIM_ENABLED && NRFX_TWIM2_ENABLED && NRFX_SPIM_ENABLED && NRFX_SPIM2_ENABLED) #endif #define NRFX_PRS_ENABLED (NRFX_PRS_BOX_0_ENABLED || NRFX_PRS_BOX_1_ENABLED || NRFX_PRS_BOX_2_ENABLED) @@ -132,4 +162,69 @@ #define NRFX_SAADC_ENABLED !(NRF51) && (MICROPY_PY_MACHINE_ADC) #define NRFX_ADC_ENABLED (NRF51) && (MICROPY_PY_MACHINE_ADC) +#if defined(NRF9160_XXAA) + +#define NRF_CLOCK NRF_CLOCK_NS +#define NRF_DPPIC NRF_DPPIC_NS +#define NRF_EGU0 NRF_EGU0_NS +#define NRF_EGU1 NRF_EGU1_NS +#define NRF_EGU2 NRF_EGU2_NS +#define NRF_EGU3 NRF_EGU3_NS +#define NRF_EGU4 NRF_EGU4_NS +#define NRF_EGU5 NRF_EGU5_NS +#define NRF_FPU NRF_FPU_NS +#define NRF_P0 NRF_P0_NS +#define NRF_I2S NRF_I2S_NS +#define NRF_KMU NRF_KMU_NS +#define NRF_NVMC NRF_NVMC_NS +#define NRF_PDM NRF_PDM_NS +#define NRF_POWER NRF_POWER_NS +#define NRF_PWM0 NRF_PWM0_NS +#define NRF_PWM1 NRF_PWM1_NS +#define NRF_PWM2 NRF_PWM2_NS +#define NRF_PWM3 NRF_PWM3_NS +#define NRF_REGULATORS NRF_REGULATORS_NS +#define NRF_RTC0 NRF_RTC0_NS +#define NRF_RTC1 NRF_RTC1_NS +#define NRF_SAADC NRF_SAADC_NS +#define NRF_SPIM0 NRF_SPIM0_NS +#define NRF_SPIM1 NRF_SPIM1_NS +#define NRF_SPIM2 NRF_SPIM2_NS +#define NRF_SPIM3 NRF_SPIM3_NS +#define NRF_SPIS0 NRF_SPIS0_NS +#define NRF_SPIS1 NRF_SPIS1_NS +#define NRF_SPIS2 NRF_SPIS2_NS +#define NRF_SPIS3 NRF_SPIS3_NS +#define NRF_TIMER0 NRF_TIMER0_NS +#define NRF_TIMER1 NRF_TIMER1_NS +#define NRF_TIMER2 NRF_TIMER2_NS +#define NRF_TWIM0 NRF_TWIM0_NS +#define NRF_TWIM1 NRF_TWIM1_NS +#define NRF_TWIM2 NRF_TWIM2_NS +#define NRF_TWIM3 NRF_TWIM3_NS +#define NRF_TWIS0 NRF_TWIS0_NS +#define NRF_TWIS1 NRF_TWIS1_NS +#define NRF_TWIS2 NRF_TWIS2_NS +#define NRF_TWIS3 NRF_TWIS3_NS +#define NRF_UARTE0 NRF_UARTE0_NS +#define NRF_UARTE1 NRF_UARTE1_NS +#define NRF_UARTE2 NRF_UARTE2_NS +#define NRF_UARTE3 NRF_UARTE3_NS +#define NRF_VMC NRF_VMC_NS +#define NRF_WDT NRF_WDT_NS +#define NRF_IPC NRF_IPC_NS + +#define NRF_CRYPTOCELL NRF_CRYPTOCELL_S +#define NRF_FICR NRF_FICR_S +#define NRF_GPIOTE0 NRF_GPIOTE0_S +#define NRF_GPIOTE1 NRF_GPIOTE1_NS +#define NRF_SPU NRF_SPU_S +#define NRF_UICR NRF_UICR_S + +#define NRF_GPIOTE NRF_GPIOTE1_NS +#define GPIOTE_IRQn GPIOTE1_IRQn +#define GPIOTE_IRQHandler GPIOTE1_IRQHandler + +#endif + #endif // NRFX_CONFIG_H diff --git a/ports/nrf/pin_defs_nrf5.h b/ports/nrf/pin_defs_nrf5.h index db05aef995059..fb2930d1d12c8 100644 --- a/ports/nrf/pin_defs_nrf5.h +++ b/ports/nrf/pin_defs_nrf5.h @@ -52,10 +52,15 @@ enum { AF_PIN_TYPE_SPI_NSS, }; +#if defined(NRF51) || defined(NRF52_SERIES) #define PIN_DEFS_PORT_AF_UNION \ NRF_UART_Type *UART; // NRF_SPI_Type *SPIM; // NRF_SPIS_Type *SPIS; +#elif defined(NRF91_SERIES) +#define PIN_DEFS_PORT_AF_UNION \ + NRF_UARTE_Type *UART; +#endif enum { PIN_ADC1 = (1 << 0), From 98c2eabaff6c049810d7cbf8aafb536080ae5b60 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Thu, 26 Sep 2019 23:59:47 +0200 Subject: [PATCH 0548/1299] nrf/boards: Add nrf9160 pca10090 board. --- ports/nrf/README.md | 3 + ports/nrf/boards/pca10090/mpconfigboard.h | 91 ++++++++++++++++++++++ ports/nrf/boards/pca10090/mpconfigboard.mk | 6 ++ ports/nrf/boards/pca10090/pins.csv | 32 ++++++++ 4 files changed, 132 insertions(+) create mode 100644 ports/nrf/boards/pca10090/mpconfigboard.h create mode 100644 ports/nrf/boards/pca10090/mpconfigboard.mk create mode 100644 ports/nrf/boards/pca10090/pins.csv diff --git a/ports/nrf/README.md b/ports/nrf/README.md index 834e2ea291a53..1b9c2ec7f0e0a 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -41,6 +41,8 @@ This is a port of MicroPython to the Nordic Semiconductor nRF series of chips. * [PCA10056](http://www.nordicsemi.com/eng/Products/nRF52840-Preview-DK) * [PCA10059](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) * [Particle Xenon](https://docs.particle.io/xenon/) +* nRF9160 + * [PCA10090](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF9160-DK) ## Compile and Flash @@ -132,6 +134,7 @@ evk_nina_b1 | s132 | Peripheral and Central | [Segge pca10056 | s140 | Peripheral and Central | [Segger](#segger-targets) pca10059 | s140 | Peripheral and Central | Manual, SWDIO and SWCLK solder points on the sides. particle_xenon | s140 | Peripheral and Central | [Black Magic Probe](#black-magic-probe-targets) +pca10090 | None (bsdlib.a) | None (LTE/GNSS) | [Segger](#segger-targets) ## IDAP-M/IDAP-Link Targets diff --git a/ports/nrf/boards/pca10090/mpconfigboard.h b/ports/nrf/boards/pca10090/mpconfigboard.h new file mode 100644 index 0000000000000..92bb61d695ed7 --- /dev/null +++ b/ports/nrf/boards/pca10090/mpconfigboard.h @@ -0,0 +1,91 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Glenn Ruben Bakke + * + * 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. + */ + +#define PCA10090 + +#define MICROPY_HW_BOARD_NAME "PCA10090" +#define MICROPY_HW_MCU_NAME "NRF9160" +#define MICROPY_PY_SYS_PLATFORM "nrf9160-DK" + +#define MICROPY_PY_MACHINE_UART (1) +#define MICROPY_PY_MACHINE_HW_PWM (0) +#define MICROPY_PY_MACHINE_HW_SPI (1) +#define MICROPY_PY_MACHINE_TIMER (0) +#define MICROPY_PY_MACHINE_RTCOUNTER (0) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_ADC (0) +#define MICROPY_PY_MACHINE_TEMP (0) +#define MICROPY_PY_RANDOM_HW_RNG (0) + +#define MICROPY_MBFS (0) + +#define MICROPY_HW_HAS_LED (1) +#define MICROPY_HW_HAS_SWITCH (0) +#define MICROPY_HW_HAS_FLASH (0) +#define MICROPY_HW_HAS_SDCARD (0) +#define MICROPY_HW_HAS_MMA7660 (0) +#define MICROPY_HW_HAS_LIS3DSH (0) +#define MICROPY_HW_HAS_LCD (0) +#define MICROPY_HW_ENABLE_RNG (0) +#define MICROPY_HW_ENABLE_RTC (0) +#define MICROPY_HW_ENABLE_TIMER (0) +#define MICROPY_HW_ENABLE_SERVO (0) +#define MICROPY_HW_ENABLE_DAC (0) +#define MICROPY_HW_ENABLE_CAN (0) + +#define MICROPY_HW_LED_COUNT (4) +#define MICROPY_HW_LED_PULLUP (0) + +#define MICROPY_HW_LED1 (2) // LED1 +#define MICROPY_HW_LED2 (3) // LED2 +#define MICROPY_HW_LED3 (4) // LED3 +#define MICROPY_HW_LED4 (5) // LED4 + +// UART config +// VCOM0 +#define MICROPY_HW_UART1_RX (28) +#define MICROPY_HW_UART1_TX (29) +#define MICROPY_HW_UART1_CTS (26) +#define MICROPY_HW_UART1_RTS (27) +#define MICROPY_HW_UART1_HWFC (1) + +/* +// VCOM2 +#define MICROPY_HW_UART1_RX (0) +#define MICROPY_HW_UART1_TX (1) +#define MICROPY_HW_UART1_CTS (15) +#define MICROPY_HW_UART1_RTS (14) +#define MICROPY_HW_UART1_HWFC (1) +*/ + +// SPI0 config +#define MICROPY_HW_SPI0_NAME "SPI0" + +#define MICROPY_HW_SPI0_SCK (13) +#define MICROPY_HW_SPI0_MOSI (11) +#define MICROPY_HW_SPI0_MISO (12) + +#define HELP_TEXT_BOARD_LED "1,2,3,4" diff --git a/ports/nrf/boards/pca10090/mpconfigboard.mk b/ports/nrf/boards/pca10090/mpconfigboard.mk new file mode 100644 index 0000000000000..9363900e2b5dd --- /dev/null +++ b/ports/nrf/boards/pca10090/mpconfigboard.mk @@ -0,0 +1,6 @@ +MCU_SERIES = m33 +MCU_VARIANT = nrf91 +MCU_SUB_VARIANT = nrf9160 +LD_FILES += boards/nrf9160_1M_256k.ld + +NRF_DEFINES += -DNRF9160_XXAA -DNRF_TRUSTZONE_NONSECURE diff --git a/ports/nrf/boards/pca10090/pins.csv b/ports/nrf/boards/pca10090/pins.csv new file mode 100644 index 0000000000000..7d060f68fff36 --- /dev/null +++ b/ports/nrf/boards/pca10090/pins.csv @@ -0,0 +1,32 @@ +P0,P0 +P1,P1 +P2,P2 +P3,P3 +P4,P4 +P5,P5 +P6,P6 +P7,P7 +P8,P8 +P9,P9 +P10,P10 +P11,P11 +P12,P12 +P13,P13 +P14,P14 +P15,P15 +P16,P16 +P17,P17 +P18,P18 +P19,P19 +P20,P20 +P21,P21 +P22,P22 +P23,P23 +P24,P24 +P25,P25 +P26,P26 +P27,P27 +P28,P28 +P29,P29 +P30,P30 +P31,P31 From 06ae818f9360e83284c64614144f1ad00998a739 Mon Sep 17 00:00:00 2001 From: ladyada Date: Thu, 3 Oct 2019 02:54:47 -0400 Subject: [PATCH 0549/1299] stm32/boards: Add new board ADAFRUIT_F405_EXPRESS. --- .../ADAFRUIT_F405_EXPRESS/mpconfigboard.h | 86 +++++++++++++++++++ .../ADAFRUIT_F405_EXPRESS/mpconfigboard.mk | 13 +++ .../boards/ADAFRUIT_F405_EXPRESS/pins.csv | 48 +++++++++++ .../stm32f4xx_hal_conf.h | 19 ++++ 4 files changed, 166 insertions(+) create mode 100644 ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h create mode 100644 ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.mk create mode 100644 ports/stm32/boards/ADAFRUIT_F405_EXPRESS/pins.csv create mode 100644 ports/stm32/boards/ADAFRUIT_F405_EXPRESS/stm32f4xx_hal_conf.h diff --git a/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h new file mode 100644 index 0000000000000..36d1d31315e38 --- /dev/null +++ b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.h @@ -0,0 +1,86 @@ +#define MICROPY_HW_BOARD_NAME "Adafruit Feather STM32F405" +#define MICROPY_HW_MCU_NAME "STM32F405RG" + +#define MICROPY_HW_HAS_SWITCH (0) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_HW_HAS_MMA7660 (0) +#define MICROPY_HW_HAS_LCD (0) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_SERVO (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_ENABLE_SDCARD (1) + +// HSE is 12MHz +#define MICROPY_HW_CLK_PLLM (12) +#define MICROPY_HW_CLK_PLLN (336) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (7) +#define MICROPY_HW_CLK_LAST_FREQ (1) + +// The Feather has a 32kHz crystal for the RTC +#define MICROPY_HW_RTC_USE_LSE (1) +#define MICROPY_HW_RTC_USE_US (0) +#define MICROPY_HW_RTC_USE_CALOUT (1) + +// UART config +#define MICROPY_HW_UART3_NAME "UART3" // on RX / TX +#define MICROPY_HW_UART3_TX (pin_B10) // TX +#define MICROPY_HW_UART3_RX (pin_B11) // RX +#define MICROPY_HW_UART3_RTS (pin_B14) // MISO +#define MICROPY_HW_UART3_CTS (pin_B13) // SCK + +#define MICROPY_HW_UART2_NAME "UART2" // on SDA/SCL +#define MICROPY_HW_UART2_TX (pin_B6) // SCL +#define MICROPY_HW_UART2_RX (pin_B7) // SDA + +#define MICROPY_HW_UART6_NAME "UART6" // on D5/D6 +#define MICROPY_HW_UART6_TX (pin_C6) // D6 +#define MICROPY_HW_UART6_RX (pin_C7) // D5 + +// I2C busses +#define MICROPY_HW_I2C1_NAME "I2C1" +#define MICROPY_HW_I2C1_SCL (pin_B6) // SCL +#define MICROPY_HW_I2C1_SDA (pin_B7) // SDA +#define MICROPY_HW_I2C2_NAME "I2C2" +#define MICROPY_HW_I2C2_SCL (pin_B10) // TX +#define MICROPY_HW_I2C2_SDA (pin_B11) // RX + +// SPI busses +#define MICROPY_HW_SPI1_NAME "SPIFLASH" +#define MICROPY_HW_SPI1_NSS (pin_A15) // FLASH CS +#define MICROPY_HW_SPI1_SCK (pin_B3) // FLASH CLK +#define MICROPY_HW_SPI1_MISO (pin_B4) // FLASH MISO +#define MICROPY_HW_SPI1_MOSI (pin_B5) // FLASH MOSI +#define MICROPY_HW_SPI2_NAME "SPI1" +#define MICROPY_HW_SPI2_NSS (pin_B12) // SD DETECT +#define MICROPY_HW_SPI2_SCK (pin_B13) // SCK +#define MICROPY_HW_SPI2_MISO (pin_B14) // MISO +#define MICROPY_HW_SPI2_MOSI (pin_B15) // MOSI + +// CAN busses +#define MICROPY_HW_CAN1_NAME "CAN1" +#define MICROPY_HW_CAN1_TX (pin_B9) // D10 +#define MICROPY_HW_CAN1_RX (pin_B8) // D9 + +// The Feather has 1 LED +#define MICROPY_HW_LED1 (pin_C1) // red +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// SD card detect switch +#define MICROPY_HW_SDCARD_DETECT_PIN (pin_B12) +#define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) +#define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) + +// USB config +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) +#define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) + +// Bootloader configuration (only needed if Mboot is used) +#define MBOOT_I2C_PERIPH_ID 1 +#define MBOOT_I2C_SCL (pin_B8) +#define MBOOT_I2C_SDA (pin_B9) +#define MBOOT_I2C_ALTFUNC (4) diff --git a/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.mk b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.mk new file mode 100644 index 0000000000000..a4430cc1df0e4 --- /dev/null +++ b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/mpconfigboard.mk @@ -0,0 +1,13 @@ +MCU_SERIES = f4 +CMSIS_MCU = STM32F405xx +AF_FILE = boards/stm32f405_af.csv +ifeq ($(USE_MBOOT),1) +# When using Mboot all the text goes together after the filesystem +LD_FILES = boards/stm32f405.ld boards/common_blifs.ld +TEXT0_ADDR = 0x08020000 +else +# When not using Mboot the ISR text goes first, then the rest after the filesystem +LD_FILES = boards/stm32f405.ld boards/common_ifs.ld +TEXT0_ADDR = 0x08000000 +TEXT1_ADDR = 0x08020000 +endif diff --git a/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/pins.csv b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/pins.csv new file mode 100644 index 0000000000000..15e810e1ae546 --- /dev/null +++ b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/pins.csv @@ -0,0 +1,48 @@ +POWER,3.3V +GND,GND +USB_ID,PA10 +USB_DM,PA11 +USB_DP,PA12 +SWDIO,PA13 +SWCLK,PA14 +FLASH_CS,PA15 +BATTERY_MONITOR,PA3 +A0,PA4 +A1,PA5 +A2,PA6 +A3,PA7 +USB_VBUS,PA9 +TX,PB10 +D1,PB10 +RX,PB11 +D0,PB11 +SD_DETECT,PB12 +SCK,PB13 +MISO,PB14 +MOSI,PB15 +BOOT1,PB2 +FLASH_SCK,PB3 +FLASH_MISO,PB4 +FLASH_MOSI,PB5 +SCL,PB6 +SDA,PB7 +D9,PB8 +D10,PB9 +D8,PC0 +NEOPIXEL,PC0 +D13,PC1 +SD_D2,PC10 +SD_D3,PC11 +SD_CK,PC12 +D12,PC2 +D11,PC3 +A4,PC4 +A5,PC5 +D6,PC6 +D5,PC7 +SD_D0,PC8 +SD_D1,PC9 +SD_CMD,PD2 +NC_A0,PA0 +NC_A1,PA1 +NC_A2,PA2 diff --git a/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/stm32f4xx_hal_conf.h b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/stm32f4xx_hal_conf.h new file mode 100644 index 0000000000000..9719157e55cdf --- /dev/null +++ b/ports/stm32/boards/ADAFRUIT_F405_EXPRESS/stm32f4xx_hal_conf.h @@ -0,0 +1,19 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H + +#include "boards/stm32f4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (12000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H From b65cc387cd0819ab97a4a8f7ebbc1f6345f65379 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 8 Oct 2019 14:25:32 +1100 Subject: [PATCH 0550/1299] extmod/modbluetooth: Allow config of scan interval/window. This adds two additional optional kwargs to `gap_scan()`: - `interval_us`: How long between scans. - `window_us`: How long to scan for during a scan. The default with NimBLE is a 11.25ms window with a 1.28s interval. Changing these parameters is important for detecting low-frequency advertisements (e.g. beacons). Note: these params are in microseconds, not milliseconds in order to allow the 625us granularity offered by the spec. --- extmod/modbluetooth.c | 29 ++++++++++++++++------------- extmod/modbluetooth.h | 2 +- extmod/modbluetooth_nimble.c | 10 +++++----- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index f4996f7e881b5..0cfa3ac0d39f3 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -501,23 +501,26 @@ STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 4, bluetooth_ble_gap_connect); STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) { - if (n_args == 2 && args[1] == mp_const_none) { - int err = mp_bluetooth_gap_scan_stop(); - return bluetooth_handle_errno(err); - } else { - mp_int_t duration_ms = 0; - if (n_args == 2) { - if (!mp_obj_is_int(args[1])) { - mp_raise_ValueError("invalid duration"); + // Default is indefinite scan, with the NimBLE "background scan" interval and window. + mp_int_t duration_ms = 0; + mp_int_t interval_us = 1280000; + mp_int_t window_us = 11250; + if (n_args > 1) { + if (args[1] == mp_const_none) { + // scan(None) --> stop scan. + return bluetooth_handle_errno(mp_bluetooth_gap_scan_stop()); + } + duration_ms = mp_obj_get_int(args[1]); + if (n_args > 2) { + interval_us = mp_obj_get_int(args[2]); + if (n_args > 3) { + window_us = mp_obj_get_int(args[3]); } - duration_ms = mp_obj_get_int(args[1]); } - - int err = mp_bluetooth_gap_scan_start(duration_ms); - return bluetooth_handle_errno(err); } + return bluetooth_handle_errno(mp_bluetooth_gap_scan_start(duration_ms, interval_us, window_us)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_scan_obj, 1, 2, bluetooth_ble_gap_scan); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_scan_obj, 1, 4, bluetooth_ble_gap_scan); #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC mp_obj_t bluetooth_ble_gap_disconnect(mp_obj_t self_in, mp_obj_t conn_handle_in) { diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 9db3bed6cd586..8f34e3484d1e7 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -186,7 +186,7 @@ int mp_bluetooth_gap_disconnect(uint16_t conn_handle); #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE // Start a discovery (scan). Set duration to zero to run continuously. -int mp_bluetooth_gap_scan_start(int32_t duration_ms); +int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us); // Stop discovery (if currently active). int mp_bluetooth_gap_scan_stop(void); diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 1e7211bfe8f1c..727894f8627e1 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -614,16 +614,16 @@ STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { return 0; } -int mp_bluetooth_gap_scan_start(int32_t duration_ms) { +int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us) { if (duration_ms == 0) { duration_ms = BLE_HS_FOREVER; } - STATIC const struct ble_gap_disc_params discover_params = { - .itvl = BLE_GAP_SCAN_SLOW_INTERVAL1, - .window = BLE_GAP_SCAN_SLOW_WINDOW1, + struct ble_gap_disc_params discover_params = { + .itvl = MAX(BLE_HCI_SCAN_ITVL_MIN, MIN(BLE_HCI_SCAN_ITVL_MAX, interval_us / BLE_HCI_SCAN_ITVL)), + .window = MAX(BLE_HCI_SCAN_WINDOW_MIN, MIN(BLE_HCI_SCAN_WINDOW_MAX, window_us / BLE_HCI_SCAN_ITVL)), .filter_policy = BLE_HCI_CONN_FILT_NO_WL, .limited = 0, - .passive = 0, + .passive = 1, // TODO: Handle BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP in gap_scan_cb above. .filter_duplicates = 0, }; int err = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, duration_ms, &discover_params, gap_scan_cb, NULL); From 76f474129e571f1de7a5e66298866675f9f2c8f1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 11 Oct 2019 13:12:59 +1100 Subject: [PATCH 0551/1299] extmod/modbluetooth: Use us instead of ms for advertising interval. This is to more accurately match the BLE spec, where intervals are configured in units of channel hop time (625us). When it was specified in ms, not all "valid" intervals were able to be specified. Now that we're also allowing configuration of scan interval, this commit updates advertising to match. --- extmod/modbluetooth.c | 10 +++++----- extmod/modbluetooth.h | 2 +- extmod/modbluetooth_nimble.c | 14 ++++---------- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 0cfa3ac0d39f3..45ca61b6f0fc9 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -301,9 +301,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_irq_obj, 1, bluetooth_ble_irq); // ---------------------------------------------------------------------------- STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_interval_ms, ARG_adv_data, ARG_resp_data, ARG_connectable }; + enum { ARG_interval_us, ARG_adv_data, ARG_resp_data, ARG_connectable }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_interval_ms, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(100)} }, + { MP_QSTR_interval_us, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(100)} }, { MP_QSTR_adv_data, MP_ARG_OBJ, {.u_obj = mp_const_none } }, { MP_QSTR_resp_data, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, { MP_QSTR_connectable, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_true } }, @@ -311,8 +311,8 @@ STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - mp_int_t interval_ms; - if (args[ARG_interval_ms].u_obj == mp_const_none || (interval_ms = mp_obj_get_int(args[ARG_interval_ms].u_obj)) == 0) { + mp_int_t interval_us; + if (args[ARG_interval_us].u_obj == mp_const_none || (interval_us = mp_obj_get_int(args[ARG_interval_us].u_obj)) == 0) { mp_bluetooth_gap_advertise_stop(); return mp_const_none; } @@ -329,7 +329,7 @@ STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_a mp_get_buffer_raise(args[ARG_resp_data].u_obj, &resp_bufinfo, MP_BUFFER_READ); } - return bluetooth_handle_errno(mp_bluetooth_gap_advertise_start(connectable, interval_ms, adv_bufinfo.buf, adv_bufinfo.len, resp_bufinfo.buf, resp_bufinfo.len)); + return bluetooth_handle_errno(mp_bluetooth_gap_advertise_start(connectable, interval_us, adv_bufinfo.buf, adv_bufinfo.len, resp_bufinfo.buf, resp_bufinfo.len)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_gap_advertise_obj, 1, bluetooth_ble_gap_advertise); diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 8f34e3484d1e7..f7284a43e8b21 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -157,7 +157,7 @@ void mp_bluetooth_get_device_addr(uint8_t *addr); // Start advertisement. Will re-start advertisement when already enabled. // Returns errno on failure. -int mp_bluetooth_gap_advertise_start(bool connectable, uint16_t interval_ms, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len); +int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len); // Stop advertisement. No-op when already stopped. void mp_bluetooth_gap_advertise_stop(void); diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 727894f8627e1..8805d410078e5 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -341,7 +341,7 @@ void mp_bluetooth_get_device_addr(uint8_t *addr) { #endif } -int mp_bluetooth_gap_advertise_start(bool connectable, uint16_t interval_ms, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) { +int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) { int ret; mp_bluetooth_gap_advertise_stop(); @@ -360,18 +360,12 @@ int mp_bluetooth_gap_advertise_start(bool connectable, uint16_t interval_ms, con } } - // Convert from 1ms to 0.625ms units. - interval_ms = interval_ms * 8 / 5; - if (interval_ms < 0x20 || interval_ms > 0x4000) { - return MP_EINVAL; - } - struct ble_gap_adv_params adv_params = { .conn_mode = connectable ? BLE_GAP_CONN_MODE_UND : BLE_GAP_CONN_MODE_NON, .disc_mode = BLE_GAP_DISC_MODE_GEN, - .itvl_min = interval_ms, - .itvl_max = interval_ms, - .channel_map = 7, // all 3 channels + .itvl_min = interval_us / BLE_HCI_ADV_ITVL, // convert to 625us units. + .itvl_max = interval_us / BLE_HCI_ADV_ITVL, + .channel_map = 7, // all 3 channels. }; ret = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL); From dc82bee298b0a9d4ba1cb85608ba85b3f3e9b77b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 8 Oct 2019 15:55:11 +1100 Subject: [PATCH 0552/1299] docs/library/bluetooth: Add initial BLE documentation. --- docs/library/bluetooth.rst | 308 +++++++++++++++++++++++++++++++++++++ docs/library/index.rst | 1 + 2 files changed, 309 insertions(+) create mode 100644 docs/library/bluetooth.rst diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst new file mode 100644 index 0000000000000..e9a803cb9b3c8 --- /dev/null +++ b/docs/library/bluetooth.rst @@ -0,0 +1,308 @@ +:mod:`bluetooth` --- low-level Bluetooth +======================================== + +.. module:: bluetooth + :synopsis: Low-level Bluetooth radio functionality + +This module provides an interface to a Bluetooth controller on a board. +Currently this supports Bluetooth Low Energy (BLE) in Central, Peripheral, +Broadcaster, and Observer roles. + +This API is intended to match the low-level Bluetooth protocol and provide +building-blocks for higher-level abstractions such as specific device types. + +class BLE +--------- + +Constructor +----------- + +.. class:: BLE() + + Returns the singleton BLE object. + +Configuration +------------- + +.. method:: BLE.active([active]) + + Optionally changes the active state of the BLE radio, and returns the + current state. + + The radio must be made active before using any other methods on this class. + +.. method:: BLE.config(name) + + Queries a configuration value by *name*. Currently supported values are: + + - ``'mac'``: Returns the device MAC address. If a device has a fixed address + (e.g. PYBD) then it will be returned. Otherwise (e.g. ESP32) a random + address will be generated when the BLE interface is made active. + +Event Handling +-------------- + +.. method:: BLE.irq(handler, trigger=0xffff) + + Registers a callback for events from the BLE stack. The *handler* takes two + arguments, ``event`` (which will be one of the codes below) and ``data`` + (which is an event-specific tuple of values). + + The optional *trigger* parameter allows you to set a mask of events that + your program is interested in. The default is all events. + + An event handler showing all possible events:: + + def bt_irq(event, data): + if event == _IRQ_CENTRAL_CONNECT: + # A central has connected to this peripheral. + conn_handle, addr_type, addr = data + elif event == _IRQ_CENTRAL_DISCONNECT: + # A central has disconnected from this peripheral. + conn_handle, addr_type, addr = data + elif event == _IRQ_GATTS_WRITE: + # A central has written to this characteristic or descriptor. + conn_handle, attr_handle = data + elif event == _IRQ_GATTS_READ_REQUEST: + # A central has issued a read. Note: this is a hard IRQ. + # Return None to deny the read. + conn_handle, attr_handle = data + elif event == _IRQ_SCAN_RESULT: + # A single scan result. + addr_type, addr, connectable, rssi, adv_data = data + elif event == _IRQ_SCAN_COMPLETE: + # Scan duration finished or manually stopped. + pass + elif event == _IRQ_PERIPHERAL_CONNECT: + # A successful gap_connect(). + conn_handle, addr_type, addr = data + elif event == _IRQ_PERIPHERAL_DISCONNECT: + # Connected peripheral has disconnected. + conn_handle, addr_type, addr = data + elif event == _IRQ_GATTC_SERVICE_RESULT: + # Called for each service found by gattc_discover_services(). + conn_handle, start_handle, end_handle, uuid = data + elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: + # Called for each characteristic found by gattc_discover_services(). + conn_handle, def_handle, value_handle, properties, uuid = data + elif event == _IRQ_GATTC_DESCRIPTOR_RESULT: + # Called for each descriptor found by gattc_discover_descriptors(). + conn_handle, dsc_handle, uuid = data + elif event == _IRQ_GATTC_READ_RESULT: + # A gattc_read() has completed. + conn_handle, value_handle, char_data = data + elif event == _IRQ_GATTC_WRITE_STATUS: + # A gattc_write() has completed. + conn_handle, value_handle, status = data + elif event == _IRQ_GATTC_NOTIFY: + # A peripheral has sent a notify request. + conn_handle, value_handle, notify_data = data + elif event == _IRQ_GATTC_INDICATE: + # A peripheral has sent an indicate request. + conn_handle, value_handle, notify_data = data + +The event codes are:: + + from micropython import const + _IRQ_CENTRAL_CONNECT = const(1 << 0) + _IRQ_CENTRAL_DISCONNECT = const(1 << 1) + _IRQ_GATTS_WRITE = const(1 << 2) + _IRQ_GATTS_READ_REQUEST = const(1 << 3) + _IRQ_SCAN_RESULT = const(1 << 4) + _IRQ_SCAN_COMPLETE = const(1 << 5) + _IRQ_PERIPHERAL_CONNECT = const(1 << 6) + _IRQ_PERIPHERAL_DISCONNECT = const(1 << 7) + _IRQ_GATTC_SERVICE_RESULT = const(1 << 8) + _IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9) + _IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10) + _IRQ_GATTC_READ_RESULT = const(1 << 11) + _IRQ_GATTC_WRITE_STATUS = const(1 << 12) + _IRQ_GATTC_NOTIFY = const(1 << 13) + _IRQ_GATTC_INDICATE = const(1 << 14) + +In order to save space in the firmware, these constants are not included on the +:mod:`bluetooth` module. Add the ones that you need from the list above to your +program. + + +Broadcaster Role (Advertiser) +----------------------------- + +.. method:: BLE.gap_advertise(interval_us, adv_data=None, resp_data=None, connectable=True) + + Starts advertising at the specified interval (in **micro**\ seconds). This + interval will be rounded down to the nearest 625us. To stop advertising, set + *interval_us* to ``None``. + + *adv_data* and *resp_data* can be any type that implements the buffer + protocol (e.g. ``bytes``, ``bytearray``, ``str``). *adv_data* is included + in all broadcasts, and *resp_data* is send in reply to an active scan. + + +Observer Role (Scanner) +----------------------- + +.. method:: BLE.gap_scan(duration_ms, [interval_us], [window_us]) + + Run a scan operation lasting for the specified duration (in **milli**\ seconds). + + To scan indefinitely, set *duration_ms* to ``0``. + + To stop scanning, set *duration_ms* to ``None``. + + Use *interval_us* and *window_us* to optionally configure the duty cycle. + The scanner will run for *window_us* **micro**\ seconds every *interval_us* + **micro**\ seconds for a total of *duration_ms* **milli**\ seconds. The default + interval and window are 1.28 seconds and 11.25 milliseconds respectively + (background scanning). + + For each scan result, the ``_IRQ_SCAN_RESULT`` event will be raised. + + When scanning is stopped (either due to the duration finishing or when + explicitly stopped), the ``_IRQ_SCAN_COMPLETE`` event will be raised. + + +Peripheral Role (GATT Server) +----------------------------- + +A BLE peripheral has a set of registered services. Each service may contain +characteristics, which each have a value. Characteristics can also contain +descriptors, which themselves have values. + +These values are stored locally and can be read from or written to by a remote +central device. Additionally, a peripheral can "notify" its value to a connected +central via its connection handle. + +.. method:: BLE.gatts_register_services(services_definition) + + Configures the peripheral with the specified services, replacing any + existing services. + + *services_definition* is a list of **services**, where each **service** is a + two-element tuple containing a UUID and a list of **characteristics**. + + Each **characteristic** is a two-or-three-element tuple containing a UUID, a + **flags** value, and optionally a list of *descriptors*. + + Each **descriptor** is a two-element tuple containing a UUID and a **flags** + value. + + The **flags** are a bitwise-OR combination of the + :data:`bluetooth.FLAGS_READ`, :data:`bluetooth.FLAGS_WRITE` and + :data:`bluetooth.FLAGS_NOTIFY` values defined below. + + The return value is a list (one element per service) of tuples (each element + is a value handle). Characteristics and descriptor handles are flattened + into the same tuple, in the order that they are defined. + + The following example registers two services (Heart Rate, and Nordic UART):: + + HR_UUID = bluetooth.UUID(0x180D) + HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) + HR_SERVICE = (HR_SERVICE, (HR_CHAR,),) + UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E') + UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) + UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,) + UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),) + SERVICES = (HR_SERVICE, UART_SERVICE,) + ( (hr,), (tx, rx,), ) = bt.gatts_register_services(SERVICES) + + The three value handles (``hr``, ``tx``, ``rx``) can be used with + :meth:`gatts_read `, :meth:`gatts_write `, + and :meth:`gatts_notify `. + + **Note:** Advertising must be stopped before registering services. + +.. method:: BLE.gatts_read(value_handle) + + Reads the local value for this handle (which has either been written by + :meth:`gatts_write ` or by a remote central). + +.. method:: BLE.gatts_write(value_handle, data) + + Writes the local value for this handle, which can be read by a central. + +.. method:: BLE.gatts_notify(conn_handle, value_handle, [data]) + + Notifies a connected central that this value has changed and that it should + issue a read of the current value from this peripheral. + + If *data* is specified, then the that value is sent to the central as part + of the notification, avoiding the need for a separate read request. Note + that this will not update the local value stored. + + +Central Role (GATT Client) +-------------------------- + +.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000) + + Connect to a peripheral. + + On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. + +.. method:: BLE.gap_disconnect(conn_handle) + + Disconnect the specified connection handle. + + On success, the ``_IRQ_PERIPHERAL_DISCONNECT`` event will be raised. + +.. method:: BLE.gattc_discover_services(conn_handle) + + Query a connected peripheral for its services. + + For each service discovered, the ``_IRQ_GATTC_SERVICE_RESULT`` event will be + raised. + +.. method:: BLE.gattc_discover_characteristics(conn_handle, start_handle, end_handle) + + Query a connected peripheral for characteristics in the specified range. + + For each characteristic discovered, the ``_IRQ_GATTC_CHARACTERISTIC_RESULT`` + event will be raised. + +.. method:: BLE.gattc_discover_descriptors(conn_handle, start_handle, end_handle) + + Query a connected peripheral for descriptors in the specified range. + + For each descriptor discovered, the ``_IRQ_GATTC_DESCRIPTOR_RESULT`` event + will be raised. + +.. method:: BLE.gattc_read(conn_handle, value_handle) + + Issue a remote read to a connected peripheral for the specified + characteristic or descriptor handle. + + On success, the ``_IRQ_GATTC_READ_RESULT`` event will be raised. + +.. method:: BLE.gattc_write(conn_handle, value_handle, data) + + Issue a remote write to a connected peripheral for the specified + characteristic or descriptor handle. + + On success, the ``_IRQ_GATTC_WRITE_STATUS`` event will be raised. + + +class UUID +---------- + + +Constructor +----------- + +.. class:: UUID(value) + + Creates a UUID instance with the specified **value**. + + The **value** can be either: + + - A 16-bit integer. e.g. ``0x2908``. + - A 128-bit UUID string. e.g. ``'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'``. + + +Constants +--------- + +.. data:: bluetooth.FLAG_READ + bluetooth.FLAG_WRITE + bluetooth.FLAG_NOTIFY diff --git a/docs/library/index.rst b/docs/library/index.rst index 4e23e6e01da84..7d4bb872cfb31 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -75,6 +75,7 @@ it will fallback to loading the built-in ``ujson`` module. builtins.rst array.rst + bluetooth.rst cmath.rst gc.rst math.rst From d5cbee3cfbc5fe41e366a55a96e2006fed819d6c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 11 Oct 2019 14:30:47 +1100 Subject: [PATCH 0553/1299] esp32: Add 4.x version of IDLE WDT config. --- ports/esp32/boards/sdkconfig.base | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index d44a97e138dd9..a11c9397f60ac 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -12,8 +12,8 @@ CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y # ESP32-specific CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n -CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=n +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n CONFIG_ESP32_XTAL_FREQ_AUTO=y # Power Management @@ -25,11 +25,16 @@ CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP=y # UDP -CONFIG_PPP_SUPPORT=y -CONFIG_PPP_PAP_SUPPORT=y -CONFIG_PPP_CHAP_SUPPORT=y +CONFIG_LWIP_PPP_SUPPORT=y +CONFIG_LWIP_PPP_PAP_SUPPORT=y +CONFIG_LWIP_PPP_CHAP_SUPPORT=y # v3.3-only (renamed in 4.0) CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=n CONFIG_SUPPORT_STATIC_ALLOCATION=y CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y +CONFIG_PPP_SUPPORT=y +CONFIG_PPP_PAP_SUPPORT=y +CONFIG_PPP_CHAP_SUPPORT=y From e0befd9e04bb79d9b74b54bacb89610731609d20 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 26 Sep 2019 23:48:30 +1000 Subject: [PATCH 0554/1299] top: Add CODEOFCONDUCT.md document based on the PSF code of conduct. --- CODEOFCONDUCT.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 CODEOFCONDUCT.md diff --git a/CODEOFCONDUCT.md b/CODEOFCONDUCT.md new file mode 100644 index 0000000000000..07cf87713bd86 --- /dev/null +++ b/CODEOFCONDUCT.md @@ -0,0 +1,53 @@ +MicroPython Code of Conduct +=========================== + +The MicroPython community is made up of members from around the globe with a +diverse set of skills, personalities, and experiences. It is through these +differences that our community experiences great successes and continued growth. +When you're working with members of the community, this Code of Conduct will +help steer your interactions and keep MicroPython a positive, successful, and +growing community. + +Members of the MicroPython community are open, considerate, and respectful. +Behaviours that reinforce these values contribute to a positive environment, and +include: acknowledging time and effort, being respectful of differing viewpoints +and experiences, gracefully accepting constructive criticism, and using +welcoming and inclusive language. + +Every member of our community has the right to have their identity respected. +The MicroPython community is dedicated to providing a positive experience for +everyone, regardless of age, gender identity and expression, sexual orientation, +disability, physical appearance, body size, ethnicity, nationality, race, or +religion (or lack thereof), education, or socio-economic status. + +Unacceptable behaviour includes: harassment, trolling, deliberate intimidation, +violent threats or language directed against another person; insults, put downs, +or jokes that are based upon stereotypes, that are exclusionary, or that hold +others up for ridicule; unwelcome sexual attention or advances; sustained +disruption of community discussions; publishing others' private information +without explicit permission; and other conduct that is inappropriate for a +professional audience including people of many different backgrounds. + +This code of conduct covers all online and offline presence related to the +MicroPython project, including GitHub and the forum. If a participant engages +in behaviour that violates this code of conduct, the MicroPython team may take +action as they deem appropriate, including warning the offender or expulsion +from the community. Community members asked to stop any inappropriate behaviour +are expected to comply immediately. + +Thank you for helping make this a welcoming, friendly community for everyone. + +If you believe that someone is violating the code of conduct, or have any other +concerns, please contact a member of the MicroPython team by emailing +contact@micropython.org. + +License +------- + +This Code of Conduct is licensed under the Creative Commons +Attribution-ShareAlike 3.0 Unported License. + +Attributions +------------ + +Based on the Python code of conduct found at https://www.python.org/psf/conduct/ From a93495b66d1e1101fffa3c8f2811d8750b5601f9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 22 Aug 2019 13:19:40 +1000 Subject: [PATCH 0555/1299] docs/reference/glossary.rst: Add new terms and reduce complexity of old. --- docs/reference/glossary.rst | 277 +++++++++++++++++++++--------------- 1 file changed, 161 insertions(+), 116 deletions(-) diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst index a6abc8b9da410..d63f372298f9e 100644 --- a/docs/reference/glossary.rst +++ b/docs/reference/glossary.rst @@ -4,152 +4,197 @@ Glossary .. glossary:: baremetal - A system without a (full-fledged) OS, for example an + A system without a (full-fledged) operating system, for example an :term:`MCU`-based system. When running on a baremetal system, - MicroPython effectively becomes its user-facing OS with a command - interpreter (REPL). + MicroPython effectively functions like a small operating system, + running user programs and providing a command interpreter + (:term:`REPL`). + + buffer protocol + Any Python object that can be automatically converted into bytes, such + as ``bytes``, ``bytearray``, ``memoryview`` and ``str`` objects, which + all implement the "buffer protocol". board - A PCB board. Oftentimes, the term is used to denote a particular - model of an :term:`MCU` system. Sometimes, it is used to actually - refer to :term:`MicroPython port` to a particular board (and then - may also refer to "boardless" ports like - :term:`Unix port `). + Typically this refers to a printed circuit board (PCB) containing a + :term:`microcontroller ` and supporting components. + MicroPython firmware is typically provided per-board, as the firmware + contains both MCU-specific functionality but also board-level + functionality such as drivers or pin names. + + bytecode + A compact representation of a Python program that generated by + compiling the Python source code. This is what the VM actually + executes. Bytecode is typically generated automatically at runtime and + is invisible to the user. Note that while :term:`CPython` and + MicroPython both use bytecode, the format is different. You can also + pre-compile source code offline using the :term:`cross-compiler`. callee-owned tuple - A tuple returned by some builtin function/method, containing data - which is valid for a limited time, usually until next call to the - same function (or a group of related functions). After next call, - data in the tuple may be changed. This leads to the following - restriction on the usage of callee-owned tuples - references to - them cannot be stored. The only valid operation is extracting - values from them (including making a copy). Callee-owned tuples - is a MicroPython-specific construct (not available in the general - Python language), introduced for memory allocation optimization. - The idea is that callee-owned tuple is allocated once and stored - on the callee side. Subsequent calls don't require allocation, - allowing to return multiple values when allocation is not possible - (e.g. in interrupt context) or not desirable (because allocation - inherently leads to memory fragmentation). Note that callee-owned - tuples are effectively mutable tuples, making an exception to - Python's rule that tuples are immutable. (It may be interesting - why tuples were used for such a purpose then, instead of mutable - lists - the reason for that is that lists are mutable from user - application side too, so a user could do things to a callee-owned - list which the callee doesn't expect and could lead to problems; - a tuple is protected from this.) + This is a MicroPython-specific construct where, for efficiency + reasons, some built-in functions or methods may re-use the same + underlying tuple object to return data. This avoids having to allocate + a new tuple for every call, and reduces heap fragmentation. Programs + should not hold references to callee-owned tuples and instead only + extract data from them (or make a copy). + + CircuitPython + A variant of MicroPython developed by `Adafruit Industries + `_. CPython - CPython is the reference implementation of Python programming - language, and the most well-known one, which most of the people - run. It is however one of many implementations (among which - Jython, IronPython, PyPy, and many more, including MicroPython). - As there is no formal specification of the Python language, only - CPython documentation, it is not always easy to draw a line - between Python the language and CPython its particular - implementation. This however leaves more freedom for other - implementations. For example, MicroPython does a lot of things - differently than CPython, while still aspiring to be a Python - language implementation. + CPython is the reference implementation of the Python programming + language, and the most well-known one. It is, however, one of many + implementations (including Jython, IronPython, PyPy, and MicroPython). + While MicroPython's implementation differs substantially from CPython, + it aims to maintain as much compatibility as possible. + + cross-compiler + Also known as ``mpy-cross``. This tool runs on your PC and converts a + :term:`.py file` containing MicroPython code into a :term:`.mpy file` + containing MicroPython bytecode. This means it loads faster (the board + doesn't have to compile the code), and uses less space on flash (the + bytecode is more space efficient). + + driver + A MicroPython library that implements support for a particular + component, such as a sensor or display. + + FFI + Acronym for Foreign Function Interface. A mechanism used by the + :term:`MicroPython Unix port` to access operating system functionality. + This is not available on :term:`baremetal` ports. + + filesystem + Most MicroPython ports and boards provide a filesystem stored in flash + that is available to user code via the standard Python file APIs such + as ``open()``. Some boards also make this internal filesystem + accessible to the host via USB mass-storage. + + frozen module + A Python module that has been cross compiled and bundled into the + firmware image. This reduces RAM requirements as the code is executed + directly from flash. + + Garbage Collector + A background process that runs in Python (and MicroPython) to reclaim + unused memory in the :term:`heap`. GPIO - General-purpose input/output. The simplest means to control - electrical signals. With GPIO, user can configure hardware - signal pin to be either input or output, and set or get - its digital signal value (logical "0" or "1"). MicroPython - abstracts GPIO access using :class:`machine.Pin` and :class:`machine.Signal` + General-purpose input/output. The simplest means to control electrical + signals (commonly referred to as "pins") on a microcontroller. GPIO + typically allows pins to be either input or output, and to set or get + their digital value (logical "0" or "1"). MicroPython abstracts GPIO + access using the :class:`machine.Pin` and :class:`machine.Signal` classes. GPIO port - A group of :term:`GPIO` pins, usually based on hardware - properties of these pins (e.g. controllable by the same - register). + A group of :term:`GPIO` pins, usually based on hardware properties of + these pins (e.g. controllable by the same register). + + heap + A region of RAM where MicroPython stores dynamic data. It is managed + automatically by the :term:`Garbage Collector`. Different MCUs and + boards have vastly different amounts of RAM available for the heap, so + this will affect how complex your program can be. interned string - A string referenced by its (unique) identity rather than its - address. Interned strings are thus can be quickly compared just - by their identifiers, instead of comparing by content. The - drawbacks of interned strings are that interning operation takes - time (proportional to the number of existing interned strings, - i.e. becoming slower and slower over time) and that the space - used for interned strings is not reclaimable. String interning - is done automatically by MicroPython compiler and runtimer when - it's either required by the implementation (e.g. function keyword - arguments are represented by interned string id's) or deemed - beneficial (e.g. for short enough strings, which have a chance - to be repeated, and thus interning them would save memory on - copies). Most of string and I/O operations don't produce interned - strings due to drawbacks described above. + An optimisation used by MicroPython to improve the efficiency of + working with strings. An interned string is referenced by its (unique) + identity rather than its address and can therefore be quickly compared + just by its identifier. It also means that identical strings can be + de-duplicated in memory. String interning is almost always invisible to + the user. MCU Microcontroller. Microcontrollers usually have much less resources - than a full-fledged computing system, but smaller, cheaper and + than a desktop, laptop, or phone, but are smaller, cheaper and require much less power. MicroPython is designed to be small and optimized enough to run on an average modern microcontroller. micropython-lib MicroPython is (usually) distributed as a single executable/binary file with just few builtin modules. There is no extensive standard - library comparable with :term:`CPython`. Instead, there is a related, but - separate project - `micropython-lib `_ - which provides implementations for many modules from CPython's - standard library. However, large subset of these modules require - POSIX-like environment (Linux, FreeBSD, MacOS, etc.; Windows may be - partially supported), and thus would work or make sense only with - `MicroPython Unix port`. Some subset of modules is however usable - for `baremetal` ports too. - - Unlike monolithic :term:`CPython` stdlib, micropython-lib modules - are intended to be installed individually - either using manual - copying or using :term:`upip`. + library comparable with :term:`CPython`'s. Instead, there is a related, + but separate project `micropython-lib + `_ which provides + implementations for many modules from CPython's standard library. + + Some of the modules are are implemented in pure Python, and are able to + be used on all ports. However, the majority of these modules use + :term:`FFI` to access operating system functionality, and as such can + only be used on the :term:`MicroPython Unix port` (with limited support + for Windows). + + Unlike the :term:`CPython` stdlib, micropython-lib modules are + intended to be installed individually - either using manual copying or + using :term:`upip`. MicroPython port - MicroPython supports different :term:`boards `, RTOSes, - and OSes, and can be relatively easily adapted to new systems. - MicroPython with support for a particular system is called a - "port" to that system. Different ports may have widely different - functionality. This documentation is intended to be a reference - of the generic APIs available across different ports ("MicroPython - core"). Note that some ports may still omit some APIs described - here (e.g. due to resource constraints). Any such differences, - and port-specific extensions beyond MicroPython core functionality, - would be described in the separate port-specific documentation. + MicroPython supports different :term:`boards `, RTOSes, and + OSes, and can be relatively easily adapted to new systems. MicroPython + with support for a particular system is called a "port" to that + system. Different ports may have widely different functionality. This + documentation is intended to be a reference of the generic APIs + available across different ports ("MicroPython core"). Note that some + ports may still omit some APIs described here (e.g. due to resource + constraints). Any such differences, and port-specific extensions + beyond the MicroPython core functionality, would be described in the + separate port-specific documentation. MicroPython Unix port - Unix port is one of the major :term:`MicroPython ports `. - It is intended to run on POSIX-compatible operating systems, like - Linux, MacOS, FreeBSD, Solaris, etc. It also serves as the basis - of Windows port. The importance of Unix port lies in the fact - that while there are many different :term:`boards `, so - two random users unlikely have the same board, almost all modern - OSes have some level of POSIX compatibility, so Unix port serves - as a kind of "common ground" to which any user can have access. - So, Unix port is used for initial prototyping, different kinds - of testing, development of machine-independent features, etc. - All users of MicroPython, even those which are interested only - in running MicroPython on :term:`MCU` systems, are recommended - to be familiar with Unix (or Windows) port, as it is important - productivity helper and a part of normal MicroPython workflow. + The unix port is one of the major :term:`MicroPython ports + `. It is intended to run on POSIX-compatible + operating systems, like Linux, MacOS, FreeBSD, Solaris, etc. It also + serves as the basis of Windows port. The Unix port is very useful for + quick development and testing of the MicroPython language and + machine-independent features. It can also function in a similar way to + :term:`CPython`'s ``python`` executable. + + .mpy file + The output of the :term:`cross-compiler`. A compiled form of a + :term:`.py file` that contains MicroPython bytecode instead of Python + source code. + + native + Usually refers to "native code", i.e. machine code for the target + microcontroller (such as ARM Thumb, Xtensa, x86/x64). The ``@native`` + decorator can be applied to a MicroPython function to generate native + code instead of bytecode for that function, which will likely be + faster but use more RAM. port - Either :term:`MicroPython port` or :term:`GPIO port`. If not clear - from context, it's recommended to use full specification like one - of the above. + Usually short for :term:`MicroPython port`, but could also refer to + :term:`GPIO port`. + + .py file + A file containing Python source code. + + REPL + An acronym for "Read, Eval, Print, Loop". This is the interactive + Python prompt, useful for debugging or testing short snippets of code. + Most MicroPython boards make a REPL available over a UART, and this is + typically accessible on a host PC via USB. stream - Also known as a "file-like object". An object which provides sequential - read-write access to the underlying data. A stream object implements - a corresponding interface, which consists of methods like ``read()``, - ``write()``, ``readinto()``, ``seek()``, ``flush()``, ``close()``, etc. - A stream is an important concept in MicroPython, many I/O objects - implement the stream interface, and thus can be used consistently and - interchangeably in different contexts. For more information on - streams in MicroPython, see `uio` module. + Also known as a "file-like object". An Python object which provides + sequential read-write access to the underlying data. A stream object + implements a corresponding interface, which consists of methods like + ``read()``, ``write()``, ``readinto()``, ``seek()``, ``flush()``, + ``close()``, etc. A stream is an important concept in MicroPython; + many I/O objects implement the stream interface, and thus can be used + consistently and interchangeably in different contexts. For more + information on streams in MicroPython, see the `uio` module. + + UART + Acronym for "Universal Asynchronous Receiver/Transmitter". This is a + peripheral that sends data over a pair of pins (TX & RX). Many boards + include a way to make at least one of the UARTs available to a host PC + as a serial port over USB. upip - (Literally, "micro pip"). A package manage for MicroPython, inspired - by :term:`CPython`'s pip, but much smaller and with reduced functionality. - upip runs both on :term:`Unix port ` and on - :term:`baremetal` ports (those which offer filesystem and networking - support). + (Literally, "micro pip"). A package manager for MicroPython, inspired + by :term:`CPython`'s pip, but much smaller and with reduced + functionality. + upip runs both on the :term:`Unix port ` and on + :term:`baremetal` ports which offer filesystem and networking support. From cfd17f4ebe0a942f02f5f515dd2da0bffb252f97 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 10 Oct 2019 00:45:27 +1100 Subject: [PATCH 0556/1299] tests/perf_bench: Add bm_fft test. This is mostly a test of complex number performance. The FFT implementation is from Project Nayuki and is MIT licensed. --- tests/perf_bench/bm_fft.py | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tests/perf_bench/bm_fft.py diff --git a/tests/perf_bench/bm_fft.py b/tests/perf_bench/bm_fft.py new file mode 100644 index 0000000000000..9ea8b08f492f4 --- /dev/null +++ b/tests/perf_bench/bm_fft.py @@ -0,0 +1,69 @@ +# Copyright (c) 2019 Project Nayuki. (MIT License) +# https://www.nayuki.io/page/free-small-fft-in-multiple-languages + +import math, cmath + +def transform_radix2(vector, inverse): + # Returns the integer whose value is the reverse of the lowest 'bits' bits of the integer 'x'. + def reverse(x, bits): + y = 0 + for i in range(bits): + y = (y << 1) | (x & 1) + x >>= 1 + return y + + # Initialization + n = len(vector) + levels = int(math.log2(n)) + coef = (2 if inverse else -2) * cmath.pi / n + exptable = [cmath.rect(1, i * coef) for i in range(n // 2)] + vector = [vector[reverse(i, levels)] for i in range(n)] # Copy with bit-reversed permutation + + # Radix-2 decimation-in-time FFT + size = 2 + while size <= n: + halfsize = size // 2 + tablestep = n // size + for i in range(0, n, size): + k = 0 + for j in range(i, i + halfsize): + temp = vector[j + halfsize] * exptable[k] + vector[j + halfsize] = vector[j] - temp + vector[j] += temp + k += tablestep + size *= 2 + return vector + +########################################################################### +# Benchmark interface + +bm_params = { + (50, 25): (2, 128), + (100, 100): (3, 256), + (1000, 1000): (20, 512), + (5000, 1000): (100, 512), +} + +def bm_setup(params): + state = None + signal = [math.cos(2 * math.pi * i / params[1]) + 0j for i in range(params[1])] + fft = None + fft_inv = None + + def run(): + nonlocal fft, fft_inv + for _ in range(params[0]): + fft = transform_radix2(signal, False) + fft_inv = transform_radix2(fft, True) + + def result(): + nonlocal fft, fft_inv + fft[1] -= 0.5 * params[1] + fft[-1] -= 0.5 * params[1] + fft_ok = all(abs(f) < 1e-3 for f in fft) + for i in range(len(fft_inv)): + fft_inv[i] -= params[1] * signal[i] + fft_inv_ok = all(abs(f) < 1e-3 for f in fft_inv) + return params[0] * params[1], (fft_ok, fft_inv_ok) + + return run, result From f1882636c0919ef16d0e549ff2dad1e5a2f59f13 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 15 Oct 2019 14:13:21 +1100 Subject: [PATCH 0557/1299] tests/run-perfbench.py: Show error when truth check fails. --- tests/run-perfbench.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index e52aa0ccbc07a..75dc0210b04dd 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -123,7 +123,6 @@ def run_benchmarks(target, param_n, param_m, n_average, test_list): _, _, result_exp = run_benchmark_on_target(PYTHON_TRUTH, test_script) if result_out != result_exp: error = 'FAIL truth' - break if error is not None: print(error) From 858e992d2e25cf50b06abc33978040092e6f1e16 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 15 Oct 2019 16:46:06 +1100 Subject: [PATCH 0558/1299] tests/run-perfbench.py: Skip complex tests if target doesn't enable it. --- tests/run-perfbench.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index 75dc0210b04dd..d02021719a41a 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -77,13 +77,17 @@ def run_benchmark_on_target(target, script): return -1, -1, 'CRASH: %r' % err def run_benchmarks(target, param_n, param_m, n_average, test_list): + skip_complex = run_feature_test(target, 'complex') != 'complex' skip_native = run_feature_test(target, 'native_check') != '' for test_file in sorted(test_list): print(test_file + ': ', end='') # Check if test should be skipped - skip = skip_native and test_file.find('viper_') != -1 + skip = ( + skip_complex and test_file.find('bm_fft') != -1 + or skip_native and test_file.find('viper_') != -1 + ) if skip: print('skip') continue From 23f0691fddfc35acd2f81f54b15ad2ecaa15c6d4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Oct 2019 15:30:16 +1100 Subject: [PATCH 0559/1299] py/persistentcode: Make .mpy more compact with qstr directly in prelude. Instead of encoding 4 zero bytes as placeholders for the simple_name and source_file qstrs, and storing the qstrs after the bytecode, store the qstrs at the location of these 4 bytes. This saves 4 bytes per bytecode function stored in a .mpy file (for example lcd160cr.mpy drops by 232 bytes, 4x 58 functions). And resulting code size is slightly reduced on ports that use this feature. --- py/persistentcode.c | 83 +++++++++++++++++++++----------------- tests/import/mpy_native.py | 4 +- tools/mpy-tool.py | 19 +++++---- 3 files changed, 57 insertions(+), 49 deletions(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index 6a8a866ac5cbd..d55e3715925f8 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -160,8 +160,8 @@ typedef struct _bytecode_prelude_t { } bytecode_prelude_t; // ip will point to start of opcodes -// ip2 will point to simple_name, source_file qstrs -STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_t *prelude) { +// return value will point to simple_name, source_file qstrs +STATIC byte *extract_prelude(const byte **ip, bytecode_prelude_t *prelude) { MP_BC_PRELUDE_SIG_DECODE(*ip); prelude->n_state = n_state; prelude->n_exc_stack = n_exc_stack; @@ -170,9 +170,10 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_ prelude->n_kwonly_args = n_kwonly_args; prelude->n_def_pos_args = n_def_pos_args; MP_BC_PRELUDE_SIZE_DECODE(*ip); - *ip2 = *ip; + byte *ip_info = (byte*)*ip; *ip += n_info; *ip += n_cell; + return ip_info; } #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE @@ -282,17 +283,28 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { } } -STATIC void load_prelude(mp_reader_t *reader, byte **ip, byte **ip2, bytecode_prelude_t *prelude) { - // Read in the prelude +STATIC void load_prelude_qstrs(mp_reader_t *reader, qstr_window_t *qw, byte *ip) { + qstr simple_name = load_qstr(reader, qw); + ip[0] = simple_name; ip[1] = simple_name >> 8; + qstr source_file = load_qstr(reader, qw); + ip[2] = source_file; ip[3] = source_file >> 8; +} + +STATIC void load_prelude(mp_reader_t *reader, qstr_window_t *qw, byte **ip, bytecode_prelude_t *prelude) { + // Read in the prelude header byte *ip_read = *ip; read_uint(reader, &ip_read); // read in n_state/etc (is effectively a var-uint) - byte *ip_read_save = ip_read; read_uint(reader, &ip_read); // read in n_info/n_cell (is effectively a var-uint) - MP_BC_PRELUDE_SIZE_DECODE(ip_read_save); - read_bytes(reader, ip_read, n_info + n_cell); // read remaining code info - // Entire prelude has been read into *ip, now decode and extract values from it - extract_prelude((const byte**)ip, (const byte**)ip2, prelude); + // Prelude header has been read into *ip, now decode and extract values from it + extract_prelude((const byte**)ip, prelude); + + // Load qstrs in prelude + load_prelude_qstrs(reader, qw, ip_read); + ip_read += 4; + + // Read remaining code info + read_bytes(reader, ip_read, *ip - ip_read); } STATIC void load_bytecode(mp_reader_t *reader, qstr_window_t *qw, byte *ip, byte *ip_top) { @@ -329,7 +341,6 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { #endif uint8_t *fun_data = NULL; - byte *ip2; bytecode_prelude_t prelude = {0}; #if MICROPY_EMIT_MACHINE_CODE size_t prelude_offset = 0; @@ -343,7 +354,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { // Load prelude byte *ip = fun_data; - load_prelude(reader, &ip, &ip2, &prelude); + load_prelude(reader, qw, &ip, &prelude); // Load bytecode load_bytecode(reader, qw, ip, fun_data + fun_data_len); @@ -377,7 +388,9 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { // Extract prelude for later use prelude_offset = read_uint(reader, NULL); const byte *ip = fun_data + prelude_offset; - extract_prelude(&ip, (const byte**)&ip2, &prelude); + byte *ip_info = extract_prelude(&ip, &prelude); + // Load qstrs in prelude + load_prelude_qstrs(reader, qw, ip_info); } else { // Load basic scope info for viper and asm prelude.scope_flags = read_uint(reader, NULL); @@ -391,14 +404,6 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { #endif } - if (kind == MP_CODE_BYTECODE || kind == MP_CODE_NATIVE_PY) { - // Load qstrs in prelude - qstr simple_name = load_qstr(reader, qw); - qstr source_file = load_qstr(reader, qw); - ip2[0] = simple_name; ip2[1] = simple_name >> 8; - ip2[2] = source_file; ip2[3] = source_file >> 8; - } - size_t n_obj = 0; size_t n_raw_code = 0; mp_uint_t *const_table = NULL; @@ -591,6 +596,11 @@ STATIC void save_obj(mp_print_t *print, mp_obj_t o) { } } +STATIC void save_prelude_qstrs(mp_print_t *print, qstr_window_t *qw, const byte *ip) { + save_qstr(print, qw, ip[0] | (ip[1] << 8)); // simple_name + save_qstr(print, qw, ip[2] | (ip[3] << 8)); // source_file +} + STATIC void save_bytecode(mp_print_t *print, qstr_window_t *qw, const byte *ip, const byte *ip_top) { while (ip < ip_top) { size_t sz; @@ -611,18 +621,21 @@ STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *q // Save function kind and data length mp_print_uint(print, (rc->fun_data_len << 2) | (rc->kind - MP_CODE_BYTECODE)); - const byte *ip2; bytecode_prelude_t prelude; if (rc->kind == MP_CODE_BYTECODE) { - // Save prelude + // Extract prelude const byte *ip = rc->fun_data; - extract_prelude(&ip, &ip2, &prelude); - size_t prelude_len = ip - (const byte*)rc->fun_data; - const byte *ip_top = (const byte*)rc->fun_data + rc->fun_data_len; - mp_print_bytes(print, rc->fun_data, prelude_len); + const byte *ip_info = extract_prelude(&ip, &prelude); + + // Save prelude + mp_print_bytes(print, rc->fun_data, ip_info - (const byte*)rc->fun_data); + save_prelude_qstrs(print, qstr_window, ip_info); + ip_info += 4; + mp_print_bytes(print, ip_info, ip - ip_info); // Save bytecode + const byte *ip_top = (const byte*)rc->fun_data + rc->fun_data_len; save_bytecode(print, qstr_window, ip, ip_top); #if MICROPY_EMIT_MACHINE_CODE } else { @@ -639,10 +652,13 @@ STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *q } if (rc->kind == MP_CODE_NATIVE_PY) { - // Save prelude size, and extract prelude for later use + // Save prelude size mp_print_uint(print, rc->prelude_offset); + + // Extract prelude and save qstrs in prelude const byte *ip = (const byte*)rc->fun_data + rc->prelude_offset; - extract_prelude(&ip, &ip2, &prelude); + const byte *ip_info = extract_prelude(&ip, &prelude); + save_prelude_qstrs(print, qstr_window, ip_info); } else { // Save basic scope info for viper and asm mp_print_uint(print, rc->scope_flags); @@ -656,12 +672,6 @@ STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *q #endif } - if (rc->kind == MP_CODE_BYTECODE || rc->kind == MP_CODE_NATIVE_PY) { - // Save qstrs in prelude - save_qstr(print, qstr_window, ip2[0] | (ip2[1] << 8)); // simple_name - save_qstr(print, qstr_window, ip2[2] | (ip2[3] << 8)); // source_file - } - if (rc->kind != MP_CODE_NATIVE_ASM) { // Save constant table for bytecode, native and viper @@ -699,9 +709,8 @@ STATIC bool mp_raw_code_has_native(mp_raw_code_t *rc) { } const byte *ip = rc->fun_data; - const byte *ip2; bytecode_prelude_t prelude; - extract_prelude(&ip, &ip2, &prelude); + extract_prelude(&ip, &prelude); const mp_uint_t *const_table = rc->const_table + prelude.n_pos_args + prelude.n_kwonly_args diff --git a/tests/import/mpy_native.py b/tests/import/mpy_native.py index 749320dbbe606..c33b3350c38d1 100644 --- a/tests/import/mpy_native.py +++ b/tests/import/mpy_native.py @@ -57,11 +57,11 @@ def open(self, path, mode): b'M\x05\x0b\x1f\x20' # header b'\x20' # n bytes, bytecode - b'\x00\x08\x00\x00\x00\x00' # prelude + b'\x00\x08\x02m\x02m' # prelude b'\x51' # LOAD_CONST_NONE b'\x63' # RETURN_VALUE - b'\x02m\x02m\x00\x02' # simple_name, source_file, n_obj, n_raw_code + b'\x00\x02' # n_obj, n_raw_code b'\x22' # n bytes, viper code b'\x00\x00\x00\x00\x00\x00' # dummy machine code diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index ab783f4184586..39362bc092652 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -583,13 +583,14 @@ def read_obj(f): else: assert 0 -def read_prelude(f, bytecode): +def read_prelude(f, bytecode, qstr_win): n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args = read_prelude_sig(lambda: read_byte(f, bytecode)) n_info, n_cell = read_prelude_size(lambda: read_byte(f, bytecode)) - l2 = bytecode.idx - for _ in range(n_info + n_cell): + read_qstr_and_pack(f, bytecode, qstr_win) # simple_name + read_qstr_and_pack(f, bytecode, qstr_win) # source_file + for _ in range(n_info - 4 + n_cell): read_byte(f, bytecode) - return l2, (n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args) + return n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args def read_qstr_and_pack(f, bytecode, qstr_win): qst = read_qstr(f, qstr_win) @@ -617,7 +618,7 @@ def read_raw_code(f, qstr_win): fun_data = BytecodeBuffer(fun_data_len) if kind == MP_CODE_BYTECODE: - name_idx, prelude = read_prelude(f, fun_data) + prelude = read_prelude(f, fun_data, qstr_win) read_bytecode(f, fun_data, qstr_win) else: fun_data.buf[:] = f.read(fun_data_len) @@ -635,6 +636,9 @@ def read_raw_code(f, qstr_win): if kind == MP_CODE_NATIVE_PY: prelude_offset = read_uint(f) _, name_idx, prelude = extract_prelude(fun_data.buf, prelude_offset) + fun_data.idx = name_idx # rewind to where qstrs are in prelude + read_qstr_and_pack(f, fun_data, qstr_win) # simple_name + read_qstr_and_pack(f, fun_data, qstr_win) # source_file else: prelude_offset = None scope_flags = read_uint(f) @@ -644,11 +648,6 @@ def read_raw_code(f, qstr_win): type_sig = read_uint(f) prelude = (None, None, scope_flags, n_pos_args, 0) - if kind in (MP_CODE_BYTECODE, MP_CODE_NATIVE_PY): - fun_data.idx = name_idx # rewind to where qstrs are in prelude - read_qstr_and_pack(f, fun_data, qstr_win) # simple_name - read_qstr_and_pack(f, fun_data, qstr_win) # source_file - qstrs = [] objs = [] raw_codes = [] From 3ee71ff314c33410964edff6e12ffc638d2df661 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 11 Oct 2019 11:48:01 +1100 Subject: [PATCH 0560/1299] minimal/frozentest.mpy: Recompile now that mpy format changed. --- ports/minimal/frozentest.mpy | Bin 200 -> 196 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/ports/minimal/frozentest.mpy b/ports/minimal/frozentest.mpy index 178b811ba0924a78ea825c22983ebbd9c597c2ff..8a89194a1048700453ca5b682c972e131a878610 100644 GIT binary patch delta 36 rcmX@Xc!W{Xmz7Cgp(#W_jDcM$tth`LHLoPKxJ0j@aw2cQ#N22AwCxKD delta 41 wcmX@Yc!H7Fmz7Cgp(#W_jGZBnaiU~^00X;JT2X#gYF Date: Mon, 14 Oct 2019 12:09:06 +1100 Subject: [PATCH 0561/1299] ports: Add new make target "submodules" which inits required modules. --- README.md | 19 ++++++++++--------- ports/esp32/Makefile | 2 ++ ports/esp32/README.md | 9 +-------- ports/esp8266/Makefile | 2 ++ ports/nrf/Makefile | 2 ++ ports/nrf/README.md | 2 +- ports/samd/Makefile | 2 ++ ports/stm32/Makefile | 2 ++ ports/stm32/README.md | 6 +++++- ports/unix/Makefile | 2 ++ py/mkrules.mk | 7 +++++++ 11 files changed, 36 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index aaf310b66285e..ed0f20091f354 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ Alternatively, fallback implementation based on setjmp/longjmp can be used. To build (see section below for required dependencies): - $ git submodule update --init $ cd ports/unix + $ make submodules $ make Then to give it a try: @@ -127,13 +127,14 @@ Debian/Ubuntu/Mint derivative Linux distros, install `build-essential` Other dependencies can be built together with MicroPython. This may be required to enable extra features or capabilities, and in recent versions of MicroPython, these may be enabled by default. To build -these additional dependencies, first fetch git submodules for them: +these additional dependencies, in the port directory you're +interested in (e.g. `ports/unix/`) first execute: - $ git submodule update --init + $ make submodules -Use the same command to get the latest versions of dependencies, as -they are updated from time to time. After that, in the port directory -(e.g. `ports/unix/`), execute: +This will fetch all the relevant git submodules (sub repositories) that +the port needs. Use the same command to get the latest versions of +submodules as they are updated from time to time. After that execute: $ make deplibs @@ -146,8 +147,8 @@ For example, to build SSL module (required for `upip` tool described above, and so enabled by dfeault), `MICROPY_PY_USSL` should be set to 1. For some ports, building required dependences is transparent, and happens -automatically. They still need to be fetched with the git submodule command -above. +automatically. But they still need to be fetched with the `make submodules` +command. The STM32 version ----------------- @@ -159,8 +160,8 @@ https://launchpad.net/gcc-arm-embedded To build: - $ git submodule update --init $ cd ports/stm32 + $ make submodules $ make You then need to get your board into DFU mode. On the pyboard, connect the diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 5d63a2586c542..2a752553e8652 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -38,6 +38,8 @@ FROZEN_MPY_DIR = modules # include py core make definitions include $(TOP)/py/py.mk +GIT_SUBMODULES = lib/berkeley-db-1.xx + PORT ?= /dev/ttyUSB0 BAUD ?= 460800 FLASH_MODE ?= dio diff --git a/ports/esp32/README.md b/ports/esp32/README.md index 2c7351ee53b55..518cafb710203 100644 --- a/ports/esp32/README.md +++ b/ports/esp32/README.md @@ -122,17 +122,10 @@ this repository): $ make -C mpy-cross ``` -The ESP32 port has a dependency on Berkeley DB, which is an external -dependency (git submodule). You'll need to have git initialize that -module using the commands: -```bash -$ git submodule init lib/berkeley-db-1.xx -$ git submodule update -``` - Then to build MicroPython for the ESP32 run: ```bash $ cd ports/esp32 +$ make submodules $ make ``` This will produce binary firmware images in the `build/` subdirectory diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 8cac07afccd8e..030f39fa916e2 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -32,6 +32,8 @@ FROZEN_MPY_DIR ?= modules # include py core make definitions include $(TOP)/py/py.mk +GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx + FWBIN = $(BUILD)/firmware-combined.bin PORT ?= /dev/ttyACM0 BAUD ?= 115200 diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index a8bd95cc6df85..62208525fe0f2 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -41,6 +41,8 @@ QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h # include py core make definitions include ../../py/py.mk +GIT_SUBMODULES = lib/nrfx lib/tinyusb + MICROPY_FATFS ?= 0 FATFS_DIR = lib/oofatfs MPY_CROSS = ../../mpy-cross/mpy-cross diff --git a/ports/nrf/README.md b/ports/nrf/README.md index 1b9c2ec7f0e0a..3c177c705c43b 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -50,11 +50,11 @@ Prerequisite steps for building the nrf port: git clone .git micropython cd micropython - git submodule update --init make -C mpy-cross By default, the PCA10040 (nrf52832) is used as compile target. To build and flash issue the following command inside the ports/nrf/ folder: + make submodules make make flash diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 77a53bd4863df..23646a4842047 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -19,6 +19,8 @@ QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h # Include py core make definitions include $(TOP)/py/py.mk +GIT_SUBMODULES = lib/asf4 lib/tinyusb + INC += -I. INC += -I$(TOP) INC += -I$(BUILD) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 28b90199aef2f..112271fe18d53 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -24,6 +24,8 @@ FROZEN_MPY_DIR ?= modules # include py core make definitions include $(TOP)/py/py.mk +GIT_SUBMODULES = lib/lwip lib/mbedtls lib/mynewt-nimble lib/stm32lib + MCU_SERIES_UPPER = $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') CMSIS_MCU_LOWER = $(shell echo $(CMSIS_MCU) | tr '[:upper:]' '[:lower:]') diff --git a/ports/stm32/README.md b/ports/stm32/README.md index a0c3b7ff39d81..f5ac362a81dbd 100644 --- a/ports/stm32/README.md +++ b/ports/stm32/README.md @@ -40,7 +40,11 @@ see [here](https://launchpad.net/gcc-arm-embedded) for the main GCC ARM Embedded page. The compiler can be changed using the `CROSS_COMPILE` variable when invoking `make`. -To build for a given board, run: +First the submodules must be obtained using: + + $ make submodules + +Then to build for a given board, run: $ make BOARD=PYBV11 diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 41552bf5c99ae..134502b4da2e7 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -16,6 +16,8 @@ UNAME_S := $(shell uname -s) # include py core make definitions include $(TOP)/py/py.mk +GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx lib/libffi + INC += -I. INC += -I$(TOP) INC += -I$(BUILD) diff --git a/py/mkrules.mk b/py/mkrules.mk index f9d77c3177afe..a75c64db93eee 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -143,6 +143,13 @@ clean-prog: .PHONY: clean-prog endif +submodules: + $(ECHO) "Updating submodules: $(GIT_SUBMODULES)" +ifneq ($(GIT_SUBMODULES),) + $(Q)git submodule update --init $(addprefix $(TOP)/,$(GIT_SUBMODULES)) +endif +.PHONY: submodules + LIBMICROPYTHON = libmicropython.a # We can execute extra commands after library creation using From f562f94e1c4ba3dd62a30b778ca6e88474fbc8e8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 14 Oct 2019 12:09:39 +1100 Subject: [PATCH 0562/1299] travis: Use "make submodules" to init required modules for each port. --- .travis.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc015bda3973e..077fca20afad5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,8 +32,8 @@ jobs: - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: - - git submodule update --init lib/lwip lib/mbedtls lib/stm32lib lib/mynewt-nimble - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/stm32 submodules - make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 @@ -66,8 +66,8 @@ jobs: - gcc --version - python3 --version script: - - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix coverage # run the main test suite @@ -87,8 +87,8 @@ jobs: - stage: test env: NAME="unix port build and tests" script: - - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix - make ${MAKEOPTS} -C ports/unix test @@ -100,8 +100,8 @@ jobs: install: - sudo apt-get install gcc-multilib libffi-dev:i386 script: - - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross PYTHON=python2 + - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix PYTHON=python2 deplibs - make ${MAKEOPTS} -C ports/unix PYTHON=python2 nanbox - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_nanbox ./run-tests) @@ -112,8 +112,8 @@ jobs: install: - sudo apt-get install clang script: - - git submodule update --init lib/axtls lib/berkeley-db-1.xx lib/libffi - make ${MAKEOPTS} -C mpy-cross CC=clang + - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix CC=clang CFLAGS_EXTRA="-DMICROPY_STACKLESS=1 -DMICROPY_STACKLESS_STRICT=1" - make ${MAKEOPTS} -C ports/unix CC=clang test @@ -149,11 +149,11 @@ jobs: - git clone https://github.com/espressif/esp-idf.git - export IDF_PATH=$(pwd)/esp-idf script: - - git submodule update --init lib/berkeley-db-1.xx - make ${MAKEOPTS} -C mpy-cross # IDF v3 build - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V3 :=" ports/esp32/Makefile | cut -d " " -f 3) - git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 + - make ${MAKEOPTS} -C ports/esp32 submodules - make ${MAKEOPTS} -C ports/esp32 # clean - git -C esp-idf clean -f -f -d components/json/cJSON components/esp32/lib components/expat/expat components/micro-ecc/micro-ecc components/nghttp/nghttp2 @@ -161,6 +161,7 @@ jobs: # IDF v4 build - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V4 :=" ports/esp32/Makefile | cut -d " " -f 3) - git -C esp-idf submodule update --init components/bt/controller/lib components/bt/host/nimble/nimble components/esp_wifi/lib_esp32 components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls + - make ${MAKEOPTS} -C ports/esp32 submodules - make ${MAKEOPTS} -C ports/esp32 # esp8266 port @@ -171,8 +172,8 @@ jobs: - zcat xtensa-lx106-elf-standalone.tar.gz | tar x - export PATH=$(pwd)/xtensa-lx106-elf/bin:$PATH script: - - git submodule update --init lib/axtls lib/berkeley-db-1.xx - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/esp8266 submodules - make ${MAKEOPTS} -C ports/esp8266 - make ${MAKEOPTS} -C ports/esp8266 BOARD=GENERIC_512K @@ -184,7 +185,7 @@ jobs: - sudo apt-get install libnewlib-arm-none-eabi - arm-none-eabi-gcc --version script: - - git submodule update --init lib/nrfx + - make ${MAKEOPTS} -C ports/nrf submodules - make ${MAKEOPTS} -C ports/nrf # bare-arm and minimal ports @@ -220,7 +221,7 @@ jobs: - sudo apt-get install gcc-arm-none-eabi - sudo apt-get install libnewlib-arm-none-eabi script: - - git submodule update --init lib/asf4 lib/tinyusb + - make ${MAKEOPTS} -C ports/samd submodules - make ${MAKEOPTS} -C ports/samd # teensy port From 418f12c5f50b6642aee0193adaa792c962226683 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 14 Oct 2019 15:39:40 +1100 Subject: [PATCH 0563/1299] extmod/modbluetooth: Increase maximum connections from 1 to 4. This avoids a confusing ENOMEM raised from gap_advertise if there is currently an active connection. This refers to the static connection buffer pre-allocated by Nimble (nothing to do with MicroPython heap memory). --- extmod/nimble/syscfg/syscfg.h | 2 +- ports/esp32/boards/sdkconfig.ble | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extmod/nimble/syscfg/syscfg.h b/extmod/nimble/syscfg/syscfg.h index 0d3acf9a7689b..485e5be3cc93e 100644 --- a/extmod/nimble/syscfg/syscfg.h +++ b/extmod/nimble/syscfg/syscfg.h @@ -40,7 +40,7 @@ int nimble_sprintf(char *str, const char *fmt, ...); /*** nimble */ #define MYNEWT_VAL_BLE_EXT_ADV (0) #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) -#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1) +#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (4) #define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0) #define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) #define MYNEWT_VAL_BLE_ROLE_CENTRAL (1) diff --git a/ports/esp32/boards/sdkconfig.ble b/ports/esp32/boards/sdkconfig.ble index db9cc1175245c..2c7c97b6123a7 100644 --- a/ports/esp32/boards/sdkconfig.ble +++ b/ports/esp32/boards/sdkconfig.ble @@ -4,3 +4,4 @@ CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= CONFIG_BTDM_CTRL_MODE_BTDM= CONFIG_BT_NIMBLE_ENABLED=y +CONFIG_BT_NIMBLE_MAX_CONNECTIONS=4 From ba16a229914e9c1a4c56ad7da41567ed8fe5b91c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 14 Oct 2019 15:44:22 +1100 Subject: [PATCH 0564/1299] extmod/modbluetooth: Clear gap_advertise payload when data is empty. Also fix default adv interval to 500ms. --- extmod/modbluetooth.c | 2 +- extmod/modbluetooth_nimble.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 45ca61b6f0fc9..5e3171e2b5088 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -303,7 +303,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_irq_obj, 1, bluetooth_ble_irq); STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_interval_us, ARG_adv_data, ARG_resp_data, ARG_connectable }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_interval_us, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(100)} }, + { MP_QSTR_interval_us, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(500000)} }, { MP_QSTR_adv_data, MP_ARG_OBJ, {.u_obj = mp_const_none } }, { MP_QSTR_resp_data, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, { MP_QSTR_connectable, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_true } }, diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 8805d410078e5..131b73574dddf 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -346,14 +346,14 @@ int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, cons mp_bluetooth_gap_advertise_stop(); - if ((adv_data != NULL) && (adv_data_len > 0)) { + if (adv_data) { ret = ble_gap_adv_set_data(adv_data, adv_data_len); if (ret != 0) { return ble_hs_err_to_errno(ret); } } - if ((sr_data != NULL) && (sr_data_len > 0)) { + if (sr_data) { ret = ble_gap_adv_rsp_set_data(sr_data, sr_data_len); if (ret != 0) { return ble_hs_err_to_errno(ret); @@ -384,6 +384,7 @@ int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, cons if (ret == 0) { return 0; } + DEBUG_EVENT_printf("ble_gap_adv_start: %d\n", ret); return ble_hs_err_to_errno(ret); } @@ -583,7 +584,7 @@ int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { - DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->disc ? event->disc.event_type : -1); + DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->type == BLE_GAP_EVENT_DISC ? event->disc.event_type : -1); if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) { mp_bluetooth_gap_on_scan_complete(); From 62e3a966fbb51f66f370523d04677a44680f0760 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 14 Oct 2019 15:45:31 +1100 Subject: [PATCH 0565/1299] docs/library/bluetooth.rst: Clarify gap_advertise adv_data behavior. Make it clear that the previous adv_data will be reused if it's not set. And some minor other improvements. --- docs/library/bluetooth.rst | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index e9a803cb9b3c8..3ab6c72b4e43d 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -6,7 +6,8 @@ This module provides an interface to a Bluetooth controller on a board. Currently this supports Bluetooth Low Energy (BLE) in Central, Peripheral, -Broadcaster, and Observer roles. +Broadcaster, and Observer roles, and a device may operate in multiple +roles concurrently. This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types. @@ -66,6 +67,7 @@ Event Handling elif event == _IRQ_GATTS_READ_REQUEST: # A central has issued a read. Note: this is a hard IRQ. # Return None to deny the read. + # Note: This event is not supported on ESP32. conn_handle, attr_handle = data elif event == _IRQ_SCAN_RESULT: # A single scan result. @@ -138,6 +140,11 @@ Broadcaster Role (Advertiser) protocol (e.g. ``bytes``, ``bytearray``, ``str``). *adv_data* is included in all broadcasts, and *resp_data* is send in reply to an active scan. + Note: if *adv_data* (or *resp_data*) is ``None``, then the data passed + to the previous call to ``gap_advertise`` will be re-used. This allows a + broadcaster to resume advertising with just ``gap_advertise(interval_us)``. + To clear the advertising payload pass an empty ``bytes``, i.e. ``b''``. + Observer Role (Scanner) ----------------------- @@ -169,9 +176,10 @@ A BLE peripheral has a set of registered services. Each service may contain characteristics, which each have a value. Characteristics can also contain descriptors, which themselves have values. -These values are stored locally and can be read from or written to by a remote -central device. Additionally, a peripheral can "notify" its value to a connected -central via its connection handle. +These values are stored locally, and are accessed by their "value handle" which +is generated during service registration. They can also be read from or written +to by a remote central device. Additionally, a peripheral can "notify" a +characteristic to a connected central via a connection handle. .. method:: BLE.gatts_register_services(services_definition) From cb73103f57aac8c5d58c4e7d495567b6fe3fa137 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 14 Oct 2019 15:48:00 +1100 Subject: [PATCH 0566/1299] extmod/modbluetooth: Fix order of params to IRQ_GATTS_WRITE event. --- extmod/modbluetooth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 5e3171e2b5088..1f247a20ca3ea 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -829,7 +829,7 @@ void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_ha schedule_ringbuf(sched); } -void mp_bluetooth_gatts_on_write(uint16_t value_handle, uint16_t conn_handle) { +void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); bool sched; From 423e67d0a000bb2379f0c2f2a93989bfa17157e0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 14 Oct 2019 23:37:35 +1100 Subject: [PATCH 0567/1299] extmod/modbluetooth: Improve ringbuf handling. No need to share the irq_data buffer with addresses. Split them into two separate buffers and manage their max length independently. --- extmod/modbluetooth.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 1f247a20ca3ea..cd8a2b0700aca 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -59,6 +59,7 @@ typedef struct { mp_obj_base_t base; mp_obj_t irq_handler; mp_obj_t irq_data_tuple; + uint8_t irq_addr_bytes[6]; uint8_t irq_data_bytes[MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN]; mp_obj_t irq_data_uuid; uint16_t irq_trigger; @@ -232,7 +233,7 @@ STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, mp_obj_bluetooth_ble_t *o = m_new_obj(mp_obj_bluetooth_ble_t); o->base.type = &bluetooth_ble_type; o->irq_handler = mp_const_none; - // Pre-allocated the event data tuple to prevent needing to allocate in the IRQ handler. + // Pre-allocate the event data tuple to prevent needing to allocate in the IRQ handler. o->irq_data_tuple = mp_obj_new_tuple(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN, NULL); mp_obj_bluetooth_uuid_t *uuid = m_new_obj(mp_obj_bluetooth_uuid_t); uuid->base.type = &bluetooth_uuid_type; @@ -287,9 +288,9 @@ STATIC mp_obj_t bluetooth_ble_irq(size_t n_args, const mp_obj_t *pos_args, mp_ma // Update the callback. MICROPY_PY_BLUETOOTH_ENTER - mp_obj_bluetooth_ble_t* bt = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bt->irq_handler = callback; - bt->irq_trigger = args[ARG_trigger].u_int; + mp_obj_bluetooth_ble_t* o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + o->irq_handler = callback; + o->irq_trigger = args[ARG_trigger].u_int; MICROPY_PY_BLUETOOTH_EXIT return mp_const_none; @@ -693,7 +694,7 @@ STATIC void ringbuf_extract(ringbuf_t* ringbuf, mp_obj_tuple_t *data_tuple, size if (bytes_addr) { bytes_addr->len = 6; for (int i = 0; i < bytes_addr->len; ++i) { - // cast away const, this is actually bt->irq_data_bytes. + // cast away const, this is actually bt->irq_addr_bytes. ((uint8_t*)bytes_addr->data)[i] = ringbuf_get(ringbuf); } data_tuple->items[j++] = MP_OBJ_FROM_PTR(bytes_addr); @@ -715,7 +716,7 @@ STATIC void ringbuf_extract(ringbuf_t* ringbuf, mp_obj_tuple_t *data_tuple, size if (bytes_data) { bytes_data->len = ringbuf_get(ringbuf); for (int i = 0; i < bytes_data->len; ++i) { - // cast away const, this is actually bt->irq_data_bytes + 6. + // cast away const, this is actually bt->irq_data_bytes. ((uint8_t*)bytes_data->data)[i] = ringbuf_get(ringbuf); } data_tuple->items[j++] = MP_OBJ_FROM_PTR(bytes_data); @@ -746,8 +747,8 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) { // Some events need to pass bytes objects to their handler, using the // pre-allocated bytes array. - mp_obj_str_t irq_data_bytes_addr = {{&mp_type_bytes}, 0, 6, o->irq_data_bytes}; - mp_obj_str_t irq_data_bytes_data = {{&mp_type_bytes}, 0, 0, o->irq_data_bytes + 6}; + mp_obj_str_t irq_data_bytes_addr = {{&mp_type_bytes}, 0, 6, o->irq_addr_bytes}; + mp_obj_str_t irq_data_bytes_data = {{&mp_type_bytes}, 0, 0, o->irq_data_bytes}; if (event == MP_BLUETOOTH_IRQ_CENTRAL_CONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT || event == MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT) { // conn_handle, addr_type, addr @@ -799,7 +800,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event, bool *sched) { *sched = false; - if (ringbuf_free(&o->ringbuf) >= len + 2 && (o->irq_trigger & event) && o->irq_handler != mp_const_none) { + if (o && ringbuf_free(&o->ringbuf) >= len + 2 && (o->irq_trigger & event) && o->irq_handler != mp_const_none) { *sched = ringbuf_avail(&o->ringbuf) == 0; ringbuf_put16(&o->ringbuf, event); return true; @@ -818,7 +819,7 @@ void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_ha MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); bool sched; - if (enqueue_irq(o, 9, event, &sched)) { + if (enqueue_irq(o, 2 + 1 + 6, event, &sched)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put(&o->ringbuf, addr_type); for (int i = 0; i < 6; ++i) { @@ -833,7 +834,7 @@ void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); bool sched; - if (enqueue_irq(o, 4, MP_BLUETOOTH_IRQ_GATTS_WRITE, &sched)) { + if (enqueue_irq(o, 2 + 2, MP_BLUETOOTH_IRQ_GATTS_WRITE, &sched)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); } @@ -856,7 +857,8 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, boo MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); bool sched; - if (enqueue_irq(o, 1 + 6 + 1 + 1 + data_len, MP_BLUETOOTH_IRQ_SCAN_RESULT, &sched)) { + data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); + if (enqueue_irq(o, 1 + 6 + 1 + 1 + 1 + data_len, MP_BLUETOOTH_IRQ_SCAN_RESULT, &sched)) { ringbuf_put(&o->ringbuf, addr_type); for (int i = 0; i < 6; ++i) { ringbuf_put(&o->ringbuf, addr[i]); @@ -864,7 +866,6 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, boo ringbuf_put(&o->ringbuf, connectable ? 1 : 0); // Note conversion of int8_t rssi to uint8_t. Must un-convert on the way out. ringbuf_put(&o->ringbuf, (uint8_t)rssi); - data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); ringbuf_put(&o->ringbuf, data_len); for (int i = 0; i < data_len; ++i) { ringbuf_put(&o->ringbuf, data[i]); @@ -920,10 +921,10 @@ void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); bool sched; + data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); if (enqueue_irq(o, 2 + 2 + 1 + data_len, event, &sched)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); - data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); ringbuf_put(&o->ringbuf, data_len); for (int i = 0; i < data_len; ++i) { ringbuf_put(&o->ringbuf, data[i]); @@ -949,6 +950,8 @@ void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_han #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK +// This can only be enabled when the thread invoking this is a MicroPython thread. +// On ESP32, for example, this is not the case. bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if ((o->irq_trigger & MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST) && o->irq_handler != mp_const_none) { From 4b2b05718a5b07a4cdf678fbe1005162b1e043ca Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 14 Oct 2019 23:40:04 +1100 Subject: [PATCH 0568/1299] esp32: Run NimBLE on the app core. This prevents issues with concurrent access to the ringbuf. MICROPY_BEGIN_ATOMIC_SECTION is only atomic to the same core. We could address this with a mutex, but it's also not safe to call mp_sched_schedule across cores. --- ports/esp32/boards/sdkconfig.ble | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/esp32/boards/sdkconfig.ble b/ports/esp32/boards/sdkconfig.ble index 2c7c97b6123a7..15422903c1890 100644 --- a/ports/esp32/boards/sdkconfig.ble +++ b/ports/esp32/boards/sdkconfig.ble @@ -3,5 +3,12 @@ CONFIG_BT_ENABLED=y CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= CONFIG_BTDM_CTRL_MODE_BTDM= + CONFIG_BT_NIMBLE_ENABLED=y + CONFIG_BT_NIMBLE_MAX_CONNECTIONS=4 + +# Pin to the same core as MP. +CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=n +CONFIG_BT_NIMBLE_PINNED_TO_CORE_1=y +CONFIG_BT_NIMBLE_PINNED_TO_CORE=1 From ea315d7d58e429d27c4d4fb4b98a432e86fdcae6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 15 Oct 2019 10:10:41 +1100 Subject: [PATCH 0569/1299] docs/library/bluetooth.rst: Explain how to increase char buffer size. --- docs/library/bluetooth.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index 3ab6c72b4e43d..6ef660416a636 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -181,6 +181,13 @@ is generated during service registration. They can also be read from or written to by a remote central device. Additionally, a peripheral can "notify" a characteristic to a connected central via a connection handle. +Characteristics and descriptors have a default maximum size of 20 bytes. +Anything written to them by a central will be truncated to this length. However, +any local write will increase the maximum size, so if you want to allow larger +writes from a central to a given characteristic, use +:meth:`gatts_write` after registration. e.g. +``gatts_write(char_handle, bytes(100))``. + .. method:: BLE.gatts_register_services(services_definition) Configures the peripheral with the specified services, replacing any From 36502bdfdcd63b2bc87027380dc63098221e8b04 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 15 Oct 2019 12:07:29 +1100 Subject: [PATCH 0570/1299] extmod/modbluetooth: Make gap_disconnect not raise when disconnected. Previously it raised OSError(MP_ENOTCONN) if the conn_handle was already disconnected. Now it returns True/False. --- docs/library/bluetooth.rst | 3 +++ extmod/modbluetooth.c | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index 6ef660416a636..00ced33e5f850 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -262,6 +262,9 @@ Central Role (GATT Client) On success, the ``_IRQ_PERIPHERAL_DISCONNECT`` event will be raised. + Returns ``False`` if the connection handle wasn't connected, and ``True`` + otherwise. + .. method:: BLE.gattc_discover_services(conn_handle) Query a connected peripheral for its services. diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index cd8a2b0700aca..6404499251a4f 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -27,6 +27,7 @@ #include "py/binary.h" #include "py/misc.h" +#include "py/mperrno.h" #include "py/obj.h" #include "py/objstr.h" #include "py/objarray.h" @@ -527,7 +528,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_scan_obj, 1, 4, blu STATIC mp_obj_t bluetooth_ble_gap_disconnect(mp_obj_t self_in, mp_obj_t conn_handle_in) { uint16_t conn_handle = mp_obj_get_int(conn_handle_in); int err = mp_bluetooth_gap_disconnect(conn_handle); - return bluetooth_handle_errno(err); + if (err == 0) { + return mp_const_true; + } else if (err == MP_ENOTCONN) { + return mp_const_false; + } else { + return bluetooth_handle_errno(err); + } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gap_disconnect_obj, bluetooth_ble_gap_disconnect); From 8f7f67123680947d7f7a38f8a2aff63c0ddd0338 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 15 Oct 2019 17:29:27 +1100 Subject: [PATCH 0571/1299] extmod/modbluetooth: In gap_advertise only accept None to stop adv. To match the docs, and interval=0 may be used in the future to indicate something else. --- extmod/modbluetooth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 6404499251a4f..3c00d5c1b596b 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -313,12 +313,12 @@ STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - mp_int_t interval_us; - if (args[ARG_interval_us].u_obj == mp_const_none || (interval_us = mp_obj_get_int(args[ARG_interval_us].u_obj)) == 0) { + if (args[ARG_interval_us].u_obj == mp_const_none) { mp_bluetooth_gap_advertise_stop(); return mp_const_none; } + mp_int_t interval_us = mp_obj_get_int(args[ARG_interval_us].u_obj); bool connectable = mp_obj_is_true(args[ARG_connectable].u_obj); mp_buffer_info_t adv_bufinfo = {0}; From 8e8cfa6f53b95fb9a7f7a430fb7bda77be56a6bd Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Oct 2019 23:22:29 +1100 Subject: [PATCH 0572/1299] tools/make-frozen.py: Allow to run with no directory passed in. In which case it will just emit empty frozen C definitions. --- tools/make-frozen.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tools/make-frozen.py b/tools/make-frozen.py index 1051b520e4e67..8809fd0c8e1ba 100755 --- a/tools/make-frozen.py +++ b/tools/make-frozen.py @@ -27,14 +27,15 @@ def module_name(f): modules = [] -root = sys.argv[1].rstrip("/") -root_len = len(root) +if len(sys.argv) > 1: + root = sys.argv[1].rstrip("/") + root_len = len(root) -for dirpath, dirnames, filenames in os.walk(root): - for f in filenames: - fullpath = dirpath + "/" + f - st = os.stat(fullpath) - modules.append((fullpath[root_len + 1:], st)) + for dirpath, dirnames, filenames in os.walk(root): + for f in filenames: + fullpath = dirpath + "/" + f + st = os.stat(fullpath) + modules.append((fullpath[root_len + 1:], st)) print("#include ") print("const char mp_frozen_str_names[] = {") From e81f538e2509938b25eb48ed2670142eed1f2573 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 00:49:02 +1000 Subject: [PATCH 0573/1299] tools: Add mechanism to provide a manifest of frozen files. This introduces a new build variable FROZEN_MANIFEST which can be set to a manifest listing (written in Python) that describes the set of files to be frozen in to the firmware. --- py/mkenv.mk | 1 + py/mkrules.mk | 6 + py/py.mk | 5 + tools/makemanifest.py | 252 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 tools/makemanifest.py diff --git a/py/mkenv.mk b/py/mkenv.mk index 0a59c2ac74ec0..70d937c450c68 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -61,6 +61,7 @@ CXX += -m32 LD += -m32 endif +MAKE_MANIFEST = $(PYTHON) $(TOP)/tools/makemanifest.py MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py MPY_CROSS = $(TOP)/mpy-cross/mpy-cross MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py diff --git a/py/mkrules.mk b/py/mkrules.mk index a75c64db93eee..2a7e1980c99c1 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -97,6 +97,12 @@ $(OBJ_DIRS): $(HEADER_BUILD): $(MKDIR) -p $@ +ifneq ($(FROZEN_MANIFEST),) +# to build frozen_content.c from a manifest +$(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h + $(Q)$(MAKE_MANIFEST) -o $@ $(TOP) $(BUILD) "$(MPY_CROSS_FLAGS)" $(FROZEN_MANIFEST) +endif + ifneq ($(FROZEN_DIR),) $(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DEPS) $(ECHO) "GEN $@" diff --git a/py/py.mk b/py/py.mk index 5669e33fccfc4..514a0e405a8d6 100644 --- a/py/py.mk +++ b/py/py.mk @@ -202,6 +202,11 @@ PY_EXTMOD_O = $(addprefix $(BUILD)/, $(PY_EXTMOD_O_BASENAME)) # this is a convenience variable for ports that want core, extmod and frozen code PY_O = $(PY_CORE_O) $(PY_EXTMOD_O) +# object file for frozen code specified via a manifest +ifneq ($(FROZEN_MANIFEST),) +PY_O += $(BUILD)/$(BUILD)/frozen_content.o +endif + # object file for frozen files ifneq ($(FROZEN_DIR),) PY_O += $(BUILD)/$(BUILD)/frozen.o diff --git a/tools/makemanifest.py b/tools/makemanifest.py new file mode 100644 index 0000000000000..3017d7a21fea6 --- /dev/null +++ b/tools/makemanifest.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2019 Damien P. George +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +from __future__ import print_function +import sys +import os +import subprocess + + +########################################################################### +# Public functions to be used in the manifest + +def include(manifest): + """Include another manifest. + + The manifest argument can be a string (filename) or an iterable of + strings. + """ + + if not isinstance(manifest, str): + for m in manifest: + include(m) + else: + with open(manifest) as f: + exec(f.read()) + +def freeze(path, script=None, opt=0): + """Freeze the input, automatically determining its type. A .py script + will be compiled to a .mpy first then frozen, and a .mpy file will be + frozen directly. + + `path` must be a directory, which is the base directory to search for + files from. When importing the resulting frozen modules, the name of + the module will start after `path`, ie `path` is excluded from the + module name. + + If `script` is None all files in `path` will be frozen. + + If `script` is an iterable then freeze() is called on all items of the + iterable (with the same `path` and `opt` passed through). + + If `script` is a string then it specifies the filename to freeze, and + can include extra directories before the file. The file will be + searched for in `path`. + + `opt` is the optimisation level to pass to mpy-cross when compiling .py + to .mpy. + """ + + freeze_internal(KIND_AUTO, path, script, opt) + +def freeze_as_str(path): + """Freeze the given `path` and all .py scripts within it as a string, + which will be compiled upon import. + """ + + freeze_internal(KIND_AS_STR, path, None, 0) + +def freeze_as_mpy(path, script=None, opt=0): + """Freeze the input (see above) by first compiling the .py scripts to + .mpy files, then freezing the resulting .mpy files. + """ + + freeze_internal(KIND_AS_MPY, path, script, opt) + +def freeze_mpy(path, script=None, opt=0): + """Freeze the input (see above), which must be .mpy files that are + frozen directly. + """ + + freeze_internal(KIND_MPY, path, script, opt) + + +########################################################################### +# Internal implementation + +KIND_AUTO = 0 +KIND_AS_STR = 1 +KIND_AS_MPY = 2 +KIND_MPY = 3 + +manifest_list = [] + +class FreezeError(Exception): + pass + +def system(cmd): + try: + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + return 0, output + except subprocess.CalledProcessError as er: + return -1, er.output + +def convert_path(path): + return path.replace('$(MPY)', TOP) + +def get_timestamp(path, default=None): + try: + stat = os.stat(path) + return stat.st_mtime + except OSError: + if default is None: + raise FreezeError('cannot stat {}'.format(path)) + return default + +def get_timestamp_newest(path): + ts_newest = 0 + for dirpath, dirnames, filenames in os.walk(path): + for f in filenames: + ts_newest = max(ts_newest, get_timestamp(os.path.join(dirpath, f))) + return ts_newest + +def mkdir(path): + cur_path = '' + for p in path.split('/')[:-1]: + cur_path += p + '/' + try: + os.mkdir(cur_path) + except OSError as er: + if er.args[0] == 17: # file exists + pass + else: + raise er + +def freeze_internal(kind, path, script, opt): + path = convert_path(path) + if script is None and kind == KIND_AS_STR: + if any(f[0] == KIND_AS_STR for f in manifest_list): + raise FreezeError('can only freeze one str directory') + manifest_list.append((KIND_AS_STR, path, script, opt)) + elif script is None: + for dirpath, dirnames, filenames in os.walk(path): + for f in filenames: + freeze_internal(kind, path, (dirpath + '/' + f)[len(path) + 1:], opt) + elif not isinstance(script, str): + for s in script: + freeze_internal(kind, path, s, opt) + else: + extension_kind = {KIND_AS_MPY: '.py', KIND_MPY: '.mpy'} + if kind == KIND_AUTO: + for k, ext in extension_kind.items(): + if script.endswith(ext): + kind = k + break + else: + raise FreezeError('unsupported file type {}'.format(script)) + wanted_extension = extension_kind[kind] + if not script.endswith(wanted_extension): + raise FreezeError('expecting a {} file, got {}'.format(wanted_extension, script)) + manifest_list.append((kind, path, script, opt)) + +def main(): + global TOP + + # Parse arguments + assert sys.argv[1] == '-o' + output_file = sys.argv[2] + TOP = sys.argv[3] + BUILD = sys.argv[4] + mpy_cross_flags = sys.argv[5] + input_manifest_list = sys.argv[6:] + + # Get paths to tools + MAKE_FROZEN = TOP + '/tools/make-frozen.py' + MPY_CROSS = TOP + '/mpy-cross/mpy-cross' + MPY_TOOL = TOP + '/tools/mpy-tool.py' + + # Include top-level inputs, to generate the manifest + for input_manifest in input_manifest_list: + try: + if input_manifest.endswith('.py'): + include(input_manifest) + else: + exec(input_manifest) + except FreezeError as er: + print('freeze error executing "{}": {}'.format(input_manifest, er.args[0])) + sys.exit(1) + + # Process the manifest + str_paths = [] + mpy_files = [] + ts_newest = 0 + for kind, path, script, opt in manifest_list: + if kind == KIND_AS_STR: + str_paths.append(path) + ts_outfile = get_timestamp_newest(path) + elif kind == KIND_AS_MPY: + infile = '{}/{}'.format(path, script) + outfile = '{}/frozen_mpy/{}.mpy'.format(BUILD, script[:-3]) + ts_infile = get_timestamp(infile) + ts_outfile = get_timestamp(outfile, 0) + if ts_infile >= ts_outfile: + print('MPY', script) + mkdir(outfile) + res, out = system([MPY_CROSS] + mpy_cross_flags.split() + ['-o', outfile, '-s', script, '-O{}'.format(opt), infile]) + if res != 0: + print('error compiling {}: {}'.format(infile, out)) + raise SystemExit(1) + ts_outfile = get_timestamp(outfile) + mpy_files.append(outfile) + else: + assert kind == KIND_MPY + infile = '{}/{}'.format(path, script) + mpy_files.append(infile) + ts_outfile = get_timestamp(infile) + ts_newest = max(ts_newest, ts_outfile) + + # Check if output file needs generating + if ts_newest < get_timestamp(output_file, 0): + # No files are newer than output file so it does not need updating + return + + # Freeze paths as strings + _, output_str = system([MAKE_FROZEN] + str_paths) + + # Freeze .mpy files + _, output_mpy = system([MPY_TOOL, '-f', '-q', BUILD + '/genhdr/qstrdefs.preprocessed.h'] + mpy_files) + + # Generate output + print('GEN', output_file) + mkdir(output_file) + with open(output_file, 'wb') as f: + f.write(b'//\n// Content for MICROPY_MODULE_FROZEN_STR\n//\n') + f.write(output_str) + f.write(b'//\n// Content for MICROPY_MODULE_FROZEN_MPY\n//\n') + f.write(output_mpy) + +if __name__ == '__main__': + main() From b1c0355b9359b0a63e08d9e5f33755f5919a6b8e Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Sep 2019 00:50:04 +1000 Subject: [PATCH 0574/1299] unix: Convert to use FROZEN_MANIFEST to specify frozen code. Removes symlinks in modules directory, all frozen code is now specified by manifest.py. --- ports/unix/Makefile | 16 +++++++++------- ports/unix/manifest.py | 2 ++ ports/unix/manifest_coverage.py | 2 ++ ports/unix/modules/upip.py | 1 - ports/unix/modules/upip_utarfile.py | 1 - 5 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 ports/unix/manifest.py create mode 100644 ports/unix/manifest_coverage.py delete mode 120000 ports/unix/modules/upip.py delete mode 120000 ports/unix/modules/upip_utarfile.py diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 134502b4da2e7..b840856ffa9f5 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -1,8 +1,10 @@ -include mpconfigport.mk include ../../py/mkenv.mk -FROZEN_DIR = scripts -FROZEN_MPY_DIR = modules +# use FROZEN_MANIFEST for new projects, others are legacy +FROZEN_MANIFEST ?= manifest.py +FROZEN_DIR = +FROZEN_MPY_DIR = # define main target PROG = micropython @@ -177,9 +179,9 @@ SRC_QSTR += $(SRC_C) $(LIB_SRC_C) # SRC_QSTR SRC_QSTR_AUTO_DEPS += -ifneq ($(FROZEN_MPY_DIR),) -# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and -# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). +ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),) +# To use frozen code create a manifest.py file with a description of files to +# freeze, then invoke make with FROZEN_MANIFEST=manifest.py (be sure to build from scratch). CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY CFLAGS += -DMPZ_DIG_SIZE=16 # force 16 bits to work on both 32 and 64 bit archs @@ -215,7 +217,7 @@ fast: # build a minimal interpreter minimal: $(MAKE) COPT="-Os -DNDEBUG" CFLAGS_EXTRA='-DMP_CONFIGFILE=""' \ - BUILD=build-minimal PROG=micropython_minimal FROZEN_DIR= FROZEN_MPY_DIR= \ + BUILD=build-minimal PROG=micropython_minimal FROZEN_MANIFEST= \ MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_SOCKET=0 MICROPY_PY_THREAD=0 \ MICROPY_PY_TERMIOS=0 MICROPY_PY_USSL=0 \ MICROPY_USE_READLINE=0 @@ -252,7 +254,7 @@ coverage: -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ -DMICROPY_UNIX_COVERAGE' \ LDFLAGS_EXTRA='-fprofile-arcs -ftest-coverage' \ - FROZEN_DIR=coverage-frzstr FROZEN_MPY_DIR=coverage-frzmpy \ + FROZEN_MANIFEST=manifest_coverage.py \ BUILD=build-coverage PROG=micropython_coverage coverage_test: coverage diff --git a/ports/unix/manifest.py b/ports/unix/manifest.py new file mode 100644 index 0000000000000..3f332446d1ac2 --- /dev/null +++ b/ports/unix/manifest.py @@ -0,0 +1,2 @@ +freeze_as_mpy('$(MPY)/tools', 'upip.py') +freeze_as_mpy('$(MPY)/tools', 'upip_utarfile.py', opt=3) diff --git a/ports/unix/manifest_coverage.py b/ports/unix/manifest_coverage.py new file mode 100644 index 0000000000000..0c32d08578e94 --- /dev/null +++ b/ports/unix/manifest_coverage.py @@ -0,0 +1,2 @@ +freeze_as_str('coverage-frzstr') +freeze_as_mpy('coverage-frzmpy') diff --git a/ports/unix/modules/upip.py b/ports/unix/modules/upip.py deleted file mode 120000 index 130eb69016485..0000000000000 --- a/ports/unix/modules/upip.py +++ /dev/null @@ -1 +0,0 @@ -../../../tools/upip.py \ No newline at end of file diff --git a/ports/unix/modules/upip_utarfile.py b/ports/unix/modules/upip_utarfile.py deleted file mode 120000 index d9653d6a60808..0000000000000 --- a/ports/unix/modules/upip_utarfile.py +++ /dev/null @@ -1 +0,0 @@ -../../../tools/upip_utarfile.py \ No newline at end of file From 2fd3f2520d88a80c12ac6c31f1e2fb1534f1aa42 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Oct 2019 23:01:29 +1100 Subject: [PATCH 0575/1299] esp8266: Convert to use FROZEN_MANIFEST to specify frozen code. Removes symlinks in modules directory, all frozen code is now specified by manifest.py. --- ports/esp8266/Makefile | 11 ++++++----- ports/esp8266/boards/manifest.py | 4 ++++ ports/esp8266/modules/dht.py | 1 - ports/esp8266/modules/ds18x20.py | 1 - ports/esp8266/modules/onewire.py | 1 - ports/esp8266/modules/upip.py | 1 - ports/esp8266/modules/upip_utarfile.py | 1 - 7 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 ports/esp8266/boards/manifest.py delete mode 120000 ports/esp8266/modules/dht.py delete mode 120000 ports/esp8266/modules/ds18x20.py delete mode 120000 ports/esp8266/modules/onewire.py delete mode 120000 ports/esp8266/modules/upip.py delete mode 120000 ports/esp8266/modules/upip_utarfile.py diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 030f39fa916e2..c4ffd4f811762 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -26,8 +26,9 @@ MICROPY_FATFS ?= 1 MICROPY_PY_BTREE ?= 1 BTREE_DEFS_EXTRA = -DDEFPSIZE=1024 -DMINCACHE=3 -FROZEN_DIR ?= scripts -FROZEN_MPY_DIR ?= modules +FROZEN_MANIFEST ?= boards/manifest.py +FROZEN_DIR ?= +FROZEN_MPY_DIR ?= # include py core make definitions include $(TOP)/py/py.mk @@ -179,9 +180,9 @@ CONFVARS_FILE = $(BUILD)/confvars ifeq ($(wildcard $(CONFVARS_FILE)),) $(shell $(MKDIR) -p $(BUILD)) -$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE)) -else ifneq ($(shell cat $(CONFVARS_FILE)), $(FROZEN_DIR) $(UART_OS)) -$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE)) +$(shell echo $(FROZEN_MANIFEST) $(UART_OS) > $(CONFVARS_FILE)) +else ifneq ($(shell cat $(CONFVARS_FILE)), $(FROZEN_MANIFEST) $(UART_OS)) +$(shell echo $(FROZEN_MANIFEST) $(UART_OS) > $(CONFVARS_FILE)) endif $(BUILD)/uart.o: $(CONFVARS_FILE) diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py new file mode 100644 index 0000000000000..1264a2268627e --- /dev/null +++ b/ports/esp8266/boards/manifest.py @@ -0,0 +1,4 @@ +freeze('modules') +freeze('$(MPY)/tools', ('upip.py', 'upip_utarfile.py')) +freeze('$(MPY)/drivers/dht', 'dht.py') +freeze('$(MPY)/drivers/onewire') diff --git a/ports/esp8266/modules/dht.py b/ports/esp8266/modules/dht.py deleted file mode 120000 index 2aa2f5cbfed8a..0000000000000 --- a/ports/esp8266/modules/dht.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/dht/dht.py \ No newline at end of file diff --git a/ports/esp8266/modules/ds18x20.py b/ports/esp8266/modules/ds18x20.py deleted file mode 120000 index 1ec92d1c9963b..0000000000000 --- a/ports/esp8266/modules/ds18x20.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/onewire/ds18x20.py \ No newline at end of file diff --git a/ports/esp8266/modules/onewire.py b/ports/esp8266/modules/onewire.py deleted file mode 120000 index 33f30e84f11cd..0000000000000 --- a/ports/esp8266/modules/onewire.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/onewire/onewire.py \ No newline at end of file diff --git a/ports/esp8266/modules/upip.py b/ports/esp8266/modules/upip.py deleted file mode 120000 index 130eb69016485..0000000000000 --- a/ports/esp8266/modules/upip.py +++ /dev/null @@ -1 +0,0 @@ -../../../tools/upip.py \ No newline at end of file diff --git a/ports/esp8266/modules/upip_utarfile.py b/ports/esp8266/modules/upip_utarfile.py deleted file mode 120000 index d9653d6a60808..0000000000000 --- a/ports/esp8266/modules/upip_utarfile.py +++ /dev/null @@ -1 +0,0 @@ -../../../tools/upip_utarfile.py \ No newline at end of file From 287800d6e1dd86f8750c432a166f36ee63cb29cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Oct 2019 23:42:20 +1100 Subject: [PATCH 0576/1299] stm32: Convert to use FROZEN_MANIFEST to specify frozen code. All symlinks are removed, frozen files are now referenced via boards/manifest.py. --- ports/stm32/Makefile | 8 ++++---- ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk | 2 +- ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.mk | 2 +- ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk | 2 +- ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk | 2 +- ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk | 2 +- ports/stm32/boards/manifest.py | 3 +++ ports/stm32/modules/dht.py | 1 - ports/stm32/modules/lcd160cr.py | 1 - ports/stm32/modules/lcd160cr_test.py | 1 - ports/stm32/modules/onewire.py | 1 - 11 files changed, 12 insertions(+), 13 deletions(-) create mode 100644 ports/stm32/boards/manifest.py delete mode 120000 ports/stm32/modules/dht.py delete mode 120000 ports/stm32/modules/lcd160cr.py delete mode 120000 ports/stm32/modules/lcd160cr_test.py delete mode 120000 ports/stm32/modules/onewire.py diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 112271fe18d53..30d4d9b48fedc 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -18,8 +18,8 @@ include $(BOARD_DIR)/mpconfigboard.mk QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h $(BUILD)/modstm_qstr.h QSTR_GLOBAL_DEPENDENCIES = mpconfigboard_common.h $(BOARD_DIR)/mpconfigboard.h -# directory containing scripts to be frozen as bytecode -FROZEN_MPY_DIR ?= modules +# File containing description of content to be frozen into firmware. +FROZEN_MANIFEST ?= boards/manifest.py # include py core make definitions include $(TOP)/py/py.mk @@ -485,13 +485,13 @@ $(TOP)/lib/stm32lib/README.md: $(ECHO) "stm32lib submodule not found, fetching it now..." (cd $(TOP) && git submodule update --init lib/stm32lib) -ifneq ($(FROZEN_DIR),) +ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),) # To use frozen source modules, put your .py files in a subdirectory (eg scripts/) # and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch). CFLAGS += -DMICROPY_MODULE_FROZEN_STR endif -ifneq ($(FROZEN_MPY_DIR),) +ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),) # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk index 084cf4d309e97..e2ced611837ee 100644 --- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk @@ -5,4 +5,4 @@ AF_FILE = boards/stm32l072_af.csv LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld # Don't include default frozen modules because MCU is tight on flash space -FROZEN_MPY_DIR ?= +FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.mk b/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.mk index 16cacc089e11f..d40825ec854ce 100644 --- a/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.mk +++ b/ports/stm32/boards/ESPRUINO_PICO/mpconfigboard.mk @@ -6,4 +6,4 @@ TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 # Don't include default frozen modules because MCU is tight on flash space -FROZEN_MPY_DIR ?= +FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk index 1d66f7e6b6952..5efa0d4a5d468 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk @@ -4,4 +4,4 @@ AF_FILE = boards/stm32f091_af.csv LD_FILES = boards/stm32f091xc.ld boards/common_basic.ld # Don't include default frozen modules because MCU is tight on flash space -FROZEN_MPY_DIR ?= +FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk index 69601f8602800..5afe134ba0973 100644 --- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk @@ -4,4 +4,4 @@ AF_FILE = boards/stm32l072_af.csv LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld # Don't include default frozen modules because MCU is tight on flash space -FROZEN_MPY_DIR ?= +FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk index 46697348fe918..7c7cd34f0e0c1 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk @@ -5,4 +5,4 @@ LD_FILES = boards/stm32l432.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg # Don't include default frozen modules because MCU is tight on flash space -FROZEN_MPY_DIR ?= +FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/manifest.py b/ports/stm32/boards/manifest.py new file mode 100644 index 0000000000000..99b08cca00c4c --- /dev/null +++ b/ports/stm32/boards/manifest.py @@ -0,0 +1,3 @@ +freeze('$(MPY)/drivers/dht', 'dht.py') +freeze('$(MPY)/drivers/display', ('lcd160cr.py', 'lcd160cr_test.py')) +freeze('$(MPY)/drivers/onewire', 'onewire.py') diff --git a/ports/stm32/modules/dht.py b/ports/stm32/modules/dht.py deleted file mode 120000 index 2aa2f5cbfed8a..0000000000000 --- a/ports/stm32/modules/dht.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/dht/dht.py \ No newline at end of file diff --git a/ports/stm32/modules/lcd160cr.py b/ports/stm32/modules/lcd160cr.py deleted file mode 120000 index 9e63f1d23f851..0000000000000 --- a/ports/stm32/modules/lcd160cr.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/display/lcd160cr.py \ No newline at end of file diff --git a/ports/stm32/modules/lcd160cr_test.py b/ports/stm32/modules/lcd160cr_test.py deleted file mode 120000 index 5f5bcc1281807..0000000000000 --- a/ports/stm32/modules/lcd160cr_test.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/display/lcd160cr_test.py \ No newline at end of file diff --git a/ports/stm32/modules/onewire.py b/ports/stm32/modules/onewire.py deleted file mode 120000 index 33f30e84f11cd..0000000000000 --- a/ports/stm32/modules/onewire.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/onewire/onewire.py \ No newline at end of file From 2e90ff7fa8f57edeaaa66aba0a6c3286cdb265d6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Oct 2019 23:49:37 +1100 Subject: [PATCH 0577/1299] qemu-arm: Convert to use FROZEN_MANIFEST to specify frozen code. --- ports/qemu-arm/Makefile | 7 +++---- ports/qemu-arm/Makefile.test | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index c730c829757d4..92574d0e11451 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -114,11 +114,10 @@ OBJ = $(OBJ_COMMON) $(OBJ_RUN) $(OBJ_TEST) # List of sources for qstr extraction SRC_QSTR += $(SRC_COMMON_C) $(SRC_RUN_C) $(LIB_SRC_C) -ifneq ($(FROZEN_MPY_DIR),) -# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and -# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). -CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool +ifneq ($(FROZEN_MANIFEST),) +CFLAGS += -DMICROPY_MODULE_FROZEN_STR CFLAGS += -DMICROPY_MODULE_FROZEN_MPY +CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool MPY_CROSS_FLAGS += -march=armv7m endif diff --git a/ports/qemu-arm/Makefile.test b/ports/qemu-arm/Makefile.test index 32ec95a4f3f86..4204a84f0d44f 100644 --- a/ports/qemu-arm/Makefile.test +++ b/ports/qemu-arm/Makefile.test @@ -1,6 +1,6 @@ LIB_SRC_C = lib/upytesthelper/upytesthelper.c -FROZEN_MPY_DIR ?= test-frzmpy +FROZEN_MANIFEST ?= "freeze('test-frzmpy')" include Makefile From ce1de1faf082abfcc5469ad3d70b88aaa0060ec3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Oct 2019 23:51:35 +1100 Subject: [PATCH 0578/1299] esp32: Convert to use FROZEN_MANIFEST to specify frozen code. All symlinks are removed. boards/manifest.py is used as a default, and can optionally use boards/manifest_release.py for more scripts. --- ports/esp32/Makefile | 3 +-- ports/esp32/boards/manifest.py | 6 ++++++ ports/esp32/boards/manifest_release.py | 8 ++++++++ ports/esp32/modules/dht.py | 1 - ports/esp32/modules/ds18x20.py | 1 - ports/esp32/modules/ntptime.py | 1 - ports/esp32/modules/onewire.py | 1 - ports/esp32/modules/umqtt/robust.py | 1 - ports/esp32/modules/umqtt/simple.py | 1 - ports/esp32/modules/upip.py | 1 - ports/esp32/modules/upip_utarfile.py | 1 - ports/esp32/modules/upysh.py | 1 - ports/esp32/modules/urequests.py | 1 - ports/esp32/modules/webrepl.py | 1 - ports/esp32/modules/webrepl_setup.py | 1 - ports/esp32/modules/websocket_helper.py | 1 - 16 files changed, 15 insertions(+), 15 deletions(-) create mode 100644 ports/esp32/boards/manifest.py create mode 100644 ports/esp32/boards/manifest_release.py delete mode 120000 ports/esp32/modules/dht.py delete mode 120000 ports/esp32/modules/ds18x20.py delete mode 120000 ports/esp32/modules/ntptime.py delete mode 120000 ports/esp32/modules/onewire.py delete mode 120000 ports/esp32/modules/umqtt/robust.py delete mode 120000 ports/esp32/modules/umqtt/simple.py delete mode 120000 ports/esp32/modules/upip.py delete mode 120000 ports/esp32/modules/upip_utarfile.py delete mode 120000 ports/esp32/modules/upysh.py delete mode 120000 ports/esp32/modules/urequests.py delete mode 120000 ports/esp32/modules/webrepl.py delete mode 120000 ports/esp32/modules/webrepl_setup.py delete mode 120000 ports/esp32/modules/websocket_helper.py diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 2a752553e8652..37261d17bd2e4 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -32,8 +32,7 @@ MICROPY_SSL_AXTLS = 0 MICROPY_FATFS = 1 MICROPY_PY_BTREE = 1 -#FROZEN_DIR = scripts -FROZEN_MPY_DIR = modules +FROZEN_MANIFEST ?= boards/manifest.py # include py core make definitions include $(TOP)/py/py.mk diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py new file mode 100644 index 0000000000000..3da8af57f8b46 --- /dev/null +++ b/ports/esp32/boards/manifest.py @@ -0,0 +1,6 @@ +freeze('modules') +freeze('$(MPY)/tools', ('upip.py', 'upip_utarfile.py')) +freeze('$(MPY)/ports/esp8266/modules', 'ntptime.py') +freeze('$(MPY)/ports/esp8266/modules', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) +freeze('$(MPY)/drivers/dht', 'dht.py') +freeze('$(MPY)/drivers/onewire') diff --git a/ports/esp32/boards/manifest_release.py b/ports/esp32/boards/manifest_release.py new file mode 100644 index 0000000000000..e56704d023453 --- /dev/null +++ b/ports/esp32/boards/manifest_release.py @@ -0,0 +1,8 @@ +include('boards/manifest.py') + +LIB = '../../../micropython-lib' + +freeze(LIB + '/upysh', 'upysh.py') +freeze(LIB + '/urequests', 'urequests.py') +freeze(LIB + '/umqtt.simple', 'umqtt/simple.py') +freeze(LIB + '/umqtt.robust', 'umqtt/robust.py') diff --git a/ports/esp32/modules/dht.py b/ports/esp32/modules/dht.py deleted file mode 120000 index 2aa2f5cbfed8a..0000000000000 --- a/ports/esp32/modules/dht.py +++ /dev/null @@ -1 +0,0 @@ -../../../drivers/dht/dht.py \ No newline at end of file diff --git a/ports/esp32/modules/ds18x20.py b/ports/esp32/modules/ds18x20.py deleted file mode 120000 index 9721929a3f0e6..0000000000000 --- a/ports/esp32/modules/ds18x20.py +++ /dev/null @@ -1 +0,0 @@ -../../esp8266/modules/ds18x20.py \ No newline at end of file diff --git a/ports/esp32/modules/ntptime.py b/ports/esp32/modules/ntptime.py deleted file mode 120000 index e90900d5a985c..0000000000000 --- a/ports/esp32/modules/ntptime.py +++ /dev/null @@ -1 +0,0 @@ -../../esp8266/modules/ntptime.py \ No newline at end of file diff --git a/ports/esp32/modules/onewire.py b/ports/esp32/modules/onewire.py deleted file mode 120000 index 091629488e0bb..0000000000000 --- a/ports/esp32/modules/onewire.py +++ /dev/null @@ -1 +0,0 @@ -../../esp8266/modules/onewire.py \ No newline at end of file diff --git a/ports/esp32/modules/umqtt/robust.py b/ports/esp32/modules/umqtt/robust.py deleted file mode 120000 index 6bfbbcf552957..0000000000000 --- a/ports/esp32/modules/umqtt/robust.py +++ /dev/null @@ -1 +0,0 @@ -../../../../../micropython-lib/umqtt.robust/umqtt/robust.py \ No newline at end of file diff --git a/ports/esp32/modules/umqtt/simple.py b/ports/esp32/modules/umqtt/simple.py deleted file mode 120000 index 6419a46647a4e..0000000000000 --- a/ports/esp32/modules/umqtt/simple.py +++ /dev/null @@ -1 +0,0 @@ -../../../../../micropython-lib/umqtt.simple/umqtt/simple.py \ No newline at end of file diff --git a/ports/esp32/modules/upip.py b/ports/esp32/modules/upip.py deleted file mode 120000 index 130eb69016485..0000000000000 --- a/ports/esp32/modules/upip.py +++ /dev/null @@ -1 +0,0 @@ -../../../tools/upip.py \ No newline at end of file diff --git a/ports/esp32/modules/upip_utarfile.py b/ports/esp32/modules/upip_utarfile.py deleted file mode 120000 index d9653d6a60808..0000000000000 --- a/ports/esp32/modules/upip_utarfile.py +++ /dev/null @@ -1 +0,0 @@ -../../../tools/upip_utarfile.py \ No newline at end of file diff --git a/ports/esp32/modules/upysh.py b/ports/esp32/modules/upysh.py deleted file mode 120000 index 12d100c29c115..0000000000000 --- a/ports/esp32/modules/upysh.py +++ /dev/null @@ -1 +0,0 @@ -../../../../micropython-lib/upysh/upysh.py \ No newline at end of file diff --git a/ports/esp32/modules/urequests.py b/ports/esp32/modules/urequests.py deleted file mode 120000 index 76661112e1c3f..0000000000000 --- a/ports/esp32/modules/urequests.py +++ /dev/null @@ -1 +0,0 @@ -../../../../micropython-lib/urequests/urequests.py \ No newline at end of file diff --git a/ports/esp32/modules/webrepl.py b/ports/esp32/modules/webrepl.py deleted file mode 120000 index 2a3987a729904..0000000000000 --- a/ports/esp32/modules/webrepl.py +++ /dev/null @@ -1 +0,0 @@ -../../esp8266/modules/webrepl.py \ No newline at end of file diff --git a/ports/esp32/modules/webrepl_setup.py b/ports/esp32/modules/webrepl_setup.py deleted file mode 120000 index 999888bf13ae7..0000000000000 --- a/ports/esp32/modules/webrepl_setup.py +++ /dev/null @@ -1 +0,0 @@ -../../esp8266/modules/webrepl_setup.py \ No newline at end of file diff --git a/ports/esp32/modules/websocket_helper.py b/ports/esp32/modules/websocket_helper.py deleted file mode 120000 index 4bcf3bcb6ab70..0000000000000 --- a/ports/esp32/modules/websocket_helper.py +++ /dev/null @@ -1 +0,0 @@ -../../esp8266/modules/websocket_helper.py \ No newline at end of file From cb2b210d45194f2578189ca5b0ec4c8b8fc96810 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 11 Oct 2019 22:19:33 +0200 Subject: [PATCH 0579/1299] stm32/adc: Update ADC driver to work with the new H7 HAL. Use NB_TO_CHANNEL to map decimal numbers to channel numbers. And use the correct rank to initialize channels (ADC_REGULAR_RANK_1). --- ports/stm32/adc.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 11b15cd09a2c6..de4b910cb6929 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -165,6 +165,13 @@ #define ADC_SCALE (ADC_SCALE_V / ((1 << ADC_CAL_BITS) - 1)) #define VREFIN_CAL ((uint16_t *)ADC_CAL_ADDRESS) +#ifndef __HAL_ADC_IS_CHANNEL_INTERNAL +#define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \ + (channel == ADC_CHANNEL_VBAT \ + || channel == ADC_CHANNEL_VREFINT \ + || channel == ADC_CHANNEL_TEMPSENSOR) +#endif + typedef struct _pyb_obj_adc_t { mp_obj_base_t base; mp_obj_t pin_name; @@ -188,8 +195,11 @@ STATIC bool is_adcx_channel(int channel) { #if defined(STM32F411xE) // The HAL has an incorrect IS_ADC_CHANNEL macro for the F411 so we check for temp return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR; -#elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) +#elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) return IS_ADC_CHANNEL(channel); +#elif defined(STM32H7) + return __HAL_ADC_IS_CHANNEL_INTERNAL(channel) + || IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel)); #elif defined(STM32L4) ADC_HandleTypeDef handle; handle.Instance = ADCx; @@ -308,8 +318,16 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) { STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) { ADC_ChannelConfTypeDef sConfig; - sConfig.Channel = channel; + #if defined (STM32H7) + sConfig.Rank = ADC_REGULAR_RANK_1; + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel) == 0) { + channel = __HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel); + } + #else sConfig.Rank = 1; + #endif + sConfig.Channel = channel; + #if defined(STM32F0) sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; #elif defined(STM32F4) || defined(STM32F7) From d523a377d17e667f760c2c64dc3a41dafe072ebc Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 11 Oct 2019 22:27:13 +0200 Subject: [PATCH 0580/1299] stm32/adc: Remove unused macro and channel check, and fix spacing. The call to is_adcx_channel is redundant because the channel is already checked just before calling adc_init_single in adc_make_new. --- ports/stm32/adc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index de4b910cb6929..ace6505a3ff1f 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -63,7 +63,6 @@ #endif #define ADCx_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE -#define ADC_NUM_CHANNELS (19) #if defined(STM32F0) @@ -293,9 +292,6 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { } STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) { - if (!is_adcx_channel(adc_obj->channel)) { - return; - } if (ADC_FIRST_GPIO_CHANNEL <= adc_obj->channel && adc_obj->channel <= ADC_LAST_GPIO_CHANNEL) { // Channels 0-16 correspond to real pins. Configure the GPIO pin in ADC mode. @@ -731,7 +727,7 @@ int adc_get_resolution(ADC_HandleTypeDef *adcHandle) { uint32_t res_reg = ADC_GET_RESOLUTION(adcHandle); switch (res_reg) { - #if !defined(STM32H7) + #if !defined(STM32H7) case ADC_RESOLUTION_6B: return 6; #endif case ADC_RESOLUTION_8B: return 8; From 4cee42d864eaabf40de6809ae76fcf20cd550a62 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 11 Oct 2019 22:36:58 +0200 Subject: [PATCH 0581/1299] stm32/adc: Use IS_CHANNEL_INTERNAL macro to check for internal channels. --- ports/stm32/adc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index ace6505a3ff1f..50abbebe155c4 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -329,9 +329,7 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) #elif defined(STM32F4) || defined(STM32F7) sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; #elif defined(STM32H7) - if (channel == ADC_CHANNEL_VREFINT - || channel == ADC_CHANNEL_TEMPSENSOR - || channel == ADC_CHANNEL_VBAT) { + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5; } else { sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5; @@ -341,9 +339,7 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.OffsetRightShift = DISABLE; sConfig.OffsetSignedSaturation = DISABLE; #elif defined(STM32L4) - if (channel == ADC_CHANNEL_VREFINT - || channel == ADC_CHANNEL_TEMPSENSOR - || channel == ADC_CHANNEL_VBAT) { + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; } else { sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; From 6e4468a2ab3be4a258d8c50929c553550301b1cb Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Fri, 11 Oct 2019 22:38:50 +0200 Subject: [PATCH 0582/1299] stm32/adc: Fix sampling for internal channels on H7 MCUs. Set to 810 cycles following HAL examples. --- ports/stm32/adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 50abbebe155c4..ca8366652ad13 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -330,7 +330,7 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; #elif defined(STM32H7) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { - sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5; + sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5; } else { sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5; } From d1ed73ca8f5034c1128de1fd995ca15eccb05ad9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 16 Oct 2019 11:23:54 +1100 Subject: [PATCH 0583/1299] docs/library/bluetooth.rst: Fix typo in HR/UART services example. --- docs/library/bluetooth.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index 00ced33e5f850..e672cef927402 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -214,7 +214,7 @@ writes from a central to a given characteristic, use HR_UUID = bluetooth.UUID(0x180D) HR_CHAR = (bluetooth.UUID(0x2A37), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) - HR_SERVICE = (HR_SERVICE, (HR_CHAR,),) + HR_SERVICE = (HR_UUID, (HR_CHAR,),) UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E') UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,) From 5463ab6df6243a63a88f686113e408933956b8eb Mon Sep 17 00:00:00 2001 From: Thiago Paes Date: Thu, 1 Nov 2018 21:47:43 -0300 Subject: [PATCH 0584/1299] docs/esp8266/tutorial: Make http_get sample function self contained. --- docs/esp8266/tutorial/network_tcp.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/esp8266/tutorial/network_tcp.rst b/docs/esp8266/tutorial/network_tcp.rst index 26a2f469ce190..852fc82f3978e 100644 --- a/docs/esp8266/tutorial/network_tcp.rst +++ b/docs/esp8266/tutorial/network_tcp.rst @@ -61,6 +61,7 @@ of the request you need to specify the page to retrieve. Let's define a function that can download and print a URL:: def http_get(url): + import socket _, _, host, path = url.split('/', 3) addr = socket.getaddrinfo(host, 80)[0][-1] s = socket.socket() @@ -74,8 +75,7 @@ Let's define a function that can download and print a URL:: break s.close() -Make sure that you import the socket module before running this function. Then -you can try:: +Then you can try:: >>> http_get('http://micropython.org/ks/test.html') From c0b3419261a7fa373d9d6f07d4bef55d019d52b9 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Mon, 5 Nov 2018 07:13:12 +0000 Subject: [PATCH 0585/1299] docs/library: Clarify relation between machine and port-specific mods. --- docs/library/index.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/library/index.rst b/docs/library/index.rst index 7d4bb872cfb31..dc89766e2d188 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -116,6 +116,19 @@ the following libraries. uctypes.rst +Port-specific libraries +----------------------- + +In some cases the following port/board-specific libraries have functions or +classes similar to those in the :mod:`machine` library. Where this occurs, the +entry in the port specific library exposes hardware functionality unique to +that platform. + +To write portable code use functions and classes from the :mod:`machine` module. +To access platform-specific hardware use the appropriate library, e.g. +:mod:`pyb` in the case of the Pyboard. + + Libraries specific to the pyboard --------------------------------- From 5a8f392f09e3826ff2a1f4330700198e9c0d42cc Mon Sep 17 00:00:00 2001 From: Mike Causer Date: Wed, 13 Feb 2019 03:20:23 +1100 Subject: [PATCH 0586/1299] docs/esp8266: Add ntptime usage to esp8266 quickref. --- docs/esp8266/quickref.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index 95ae55b570682..a50e3dd6b5b42 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -243,6 +243,12 @@ See :ref:`machine.RTC ` :: rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time rtc.datetime() # get date and time + # synchronize with ntp + # need to be connected to wifi + import ntptime + ntptime.settime() # set the rtc datetime from the remote server + rtc.datetime() # get the date and time in UTC + Deep-sleep mode --------------- From a2c4cb484d6018a65dabd921c509fc12b71a088b Mon Sep 17 00:00:00 2001 From: Mike Causer Date: Wed, 13 Feb 2019 12:29:01 +1100 Subject: [PATCH 0587/1299] docs: Fix spelling in various parts of the docs. --- docs/esp32/quickref.rst | 6 +++--- docs/esp8266/general.rst | 2 +- docs/esp8266/quickref.rst | 2 +- docs/library/network.rst | 2 +- docs/library/uhashlib.rst | 4 ++-- docs/library/uos.rst | 4 ++-- docs/pyboard/tutorial/leds.rst | 2 +- docs/reference/packages.rst | 4 ++-- docs/reference/speed_python.rst | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index dd85b102b2551..20e728d1c7d89 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -77,7 +77,7 @@ The :mod:`network` module:: wlan.scan() # scan for access points wlan.isconnected() # check if the station is connected to an AP wlan.connect('essid', 'password') # connect to an AP - wlan.config('mac') # get the interface's MAC adddress + wlan.config('mac') # get the interface's MAC address wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses ap = network.WLAN(network.AP_IF) # create access-point interface @@ -203,7 +203,7 @@ Use the :ref:`machine.ADC ` class:: adc = ADC(Pin(32)) # create ADC object on ADC pin adc.read() # read value, 0-4095 across voltage range 0.0v - 1.0v - adc.atten(ADC.ATTN_11DB) # set 11dB input attentuation (voltage range roughly 0.0v - 3.6v) + adc.atten(ADC.ATTN_11DB) # set 11dB input attenuation (voltage range roughly 0.0v - 3.6v) adc.width(ADC.WIDTH_9BIT) # set 9 bit return values (returned range 0-511) adc.read() # read value using the newly configured attenuation and width @@ -257,7 +257,7 @@ class:: spi.init(baudrate=200000) # set the baudrate spi.read(10) # read 10 bytes on MISO - spi.read(10, 0xff) # read 10 bytes while outputing 0xff on MOSI + spi.read(10, 0xff) # read 10 bytes while outputting 0xff on MOSI buf = bytearray(50) # create a buffer spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case) diff --git a/docs/esp8266/general.rst b/docs/esp8266/general.rst index 020e21df62d09..fbe8fe1c3cabd 100644 --- a/docs/esp8266/general.rst +++ b/docs/esp8266/general.rst @@ -140,7 +140,7 @@ The above may also happen after an application terminates and quits to the REPL for any reason including an exception. Subsequent arrival of data provokes the failure with the above error message repeatedly issued. So, sockets should be closed in any case, regardless whether an application terminates successfully -or by an exeption, for example using try/finally:: +or by an exception, for example using try/finally:: sock = socket(...) try: diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index a50e3dd6b5b42..a1976650436ce 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -188,7 +188,7 @@ class:: spi.init(baudrate=200000) # set the baudrate spi.read(10) # read 10 bytes on MISO - spi.read(10, 0xff) # read 10 bytes while outputing 0xff on MOSI + spi.read(10, 0xff) # read 10 bytes while outputting 0xff on MOSI buf = bytearray(50) # create a buffer spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case) diff --git a/docs/library/network.rst b/docs/library/network.rst index 0c5659244c607..01e6f61369a40 100644 --- a/docs/library/network.rst +++ b/docs/library/network.rst @@ -68,7 +68,7 @@ parameter should be `id`. (password) required to access said service. There can be further arbitrary keyword-only parameters, depending on the networking medium type and/or particular device. Parameters can be used to: a) - specify alternative service identifer types; b) provide additional + specify alternative service identifier types; b) provide additional connection parameters. For various medium types, there are different sets of predefined/recommended parameters, among them: diff --git a/docs/library/uhashlib.rst b/docs/library/uhashlib.rst index 50ed658cc1039..e1eddd2b7131f 100644 --- a/docs/library/uhashlib.rst +++ b/docs/library/uhashlib.rst @@ -18,10 +18,10 @@ be implemented: * SHA1 - A previous generation algorithm. Not recommended for new usages, but SHA1 is a part of number of Internet standards and existing applications, so boards targeting network connectivity and - interoperatiability will try to provide this. + interoperability will try to provide this. * MD5 - A legacy algorithm, not considered cryptographically secure. Only - selected boards, targeting interoperatibility with legacy applications, + selected boards, targeting interoperability with legacy applications, will offer this. Constructors diff --git a/docs/library/uos.rst b/docs/library/uos.rst index c7460134b1339..58ac83b2b123b 100644 --- a/docs/library/uos.rst +++ b/docs/library/uos.rst @@ -94,10 +94,10 @@ Filesystem access * ``f_frsize`` -- fragment size * ``f_blocks`` -- size of fs in f_frsize units * ``f_bfree`` -- number of free blocks - * ``f_bavail`` -- number of free blocks for unpriviliged users + * ``f_bavail`` -- number of free blocks for unprivileged users * ``f_files`` -- number of inodes * ``f_ffree`` -- number of free inodes - * ``f_favail`` -- number of free inodes for unpriviliged users + * ``f_favail`` -- number of free inodes for unprivileged users * ``f_flag`` -- mount flags * ``f_namemax`` -- maximum filename length diff --git a/docs/pyboard/tutorial/leds.rst b/docs/pyboard/tutorial/leds.rst index 6b05f5db05042..2b76d17cde77f 100644 --- a/docs/pyboard/tutorial/leds.rst +++ b/docs/pyboard/tutorial/leds.rst @@ -20,7 +20,7 @@ When you save, the red light on the pyboard should turn on for about a second. T So what does this code do? First we need some terminology. Python is an object-oriented language, almost everything in python is a *class* and when you create an instance of a class you get an *object*. Classes have *methods* associated to them. A method (also called a member function) is used to interact with or control the object. -The first line of code creates an LED object which we have then called led. When we create the object, it takes a single parameter which must be between 1 and 4, corresponding to the 4 LEDs on the board. The pyb.LED class has three important member functions that we will use: on(), off() and toggle(). The other function that we use is pyb.delay() this simply waits for a given time in miliseconds. Once we have created the LED object, the statement while True: creates an infinite loop which toggles the led between on and off and waits for 1 second. +The first line of code creates an LED object which we have then called led. When we create the object, it takes a single parameter which must be between 1 and 4, corresponding to the 4 LEDs on the board. The pyb.LED class has three important member functions that we will use: on(), off() and toggle(). The other function that we use is pyb.delay() this simply waits for a given time in milliseconds. Once we have created the LED object, the statement while True: creates an infinite loop which toggles the led between on and off and waits for 1 second. **Exercise: Try changing the time between toggling the led and turning on a different LED.** diff --git a/docs/reference/packages.rst b/docs/reference/packages.rst index 8be2461c2dbc0..43217493e52a4 100644 --- a/docs/reference/packages.rst +++ b/docs/reference/packages.rst @@ -39,7 +39,7 @@ The MicroPython distribution package format is a well-known tar.gz format, with some adaptations however. The Gzip compressor, used as an external wrapper for TAR archives, by default uses 32KB dictionary size, which means that to uncompress a compressed stream, 32KB of -contguous memory needs to be allocated. This requirement may be not +contiguous memory needs to be allocated. This requirement may be not satisfiable on low-memory devices, which may have total memory available less than that amount, and even if not, a contiguous block like that may be hard to allocate due to memory fragmentation. To accommodate @@ -132,7 +132,7 @@ Installing to a directory image involves using ``-p`` switch to `upip`:: micropython -m upip install -p install_dir micropython-pystone_lowmem -After this command, the package content (and contents of every depenency +After this command, the package content (and contents of every dependency packages) will be available in the ``install_dir/`` subdirectory. You would need to transfer contents of this directory (without the ``install_dir/`` prefix) to the device, at the suitable location, where diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst index aa0b54cb50ed7..a6951ed334856 100644 --- a/docs/reference/speed_python.rst +++ b/docs/reference/speed_python.rst @@ -214,7 +214,7 @@ There are certain limitations in the current implementation of the native code e * Generators are not supported. * If ``raise`` is used an argument must be supplied. -The trade-off for the improved performance (roughly twices as fast as bytecode) is an +The trade-off for the improved performance (roughly twice as fast as bytecode) is an increase in compiled code size. The Viper code emitter From 615d6b3c66da710d2b43de9ad889eae4fd6bd366 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Fri, 15 Feb 2019 20:16:41 +0200 Subject: [PATCH 0588/1299] docs/wipy/tutorial: Link Blynk examples to the official library. --- docs/wipy/tutorial/blynk.rst | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/wipy/tutorial/blynk.rst b/docs/wipy/tutorial/blynk.rst index b5a2f24a472cb..b34ea17ae1cb5 100644 --- a/docs/wipy/tutorial/blynk.rst +++ b/docs/wipy/tutorial/blynk.rst @@ -1,19 +1,17 @@ Getting started with Blynk and the WiPy --------------------------------------- -Blynk is a platform with iOS and Android apps to control -Arduino, Raspberry Pi and the likes over the Internet. -You can easily build graphic interfaces for all your -projects by simply dragging and dropping widgets. +Blynk provides iOS and Android apps to control any hardware over the Internet +or directly using Bluetooth. You can easily build graphic interfaces for all +your projects by simply dragging and dropping widgets, right on your smartphone. -There are several examples available that work out-of-the-box with -the WiPy. Before anything else, make sure that your WiPy is running +Before anything else, make sure that your WiPy is running the latest software, check :ref:`OTA How-To ` for instructions. -1. Get the `Blynk library `_ and put it in ``/flash/lib/`` via FTP. -2. Get the `Blynk examples `_, edit the network settings, and afterwards - upload them to ``/flash/lib/`` via FTP as well. +1. Get the `Blynk library `_ and put it in ``/flash/lib/`` via FTP. +2. Get the `Blynk example for WiPy `_, edit the network settings, and afterwards + upload it to ``/flash/`` via FTP as well. 3. Follow the instructions on each example to setup the Blynk dashboard on your smartphone or tablet. 4. Give it a try, for instance:: - >>> execfile('01_simple.py') + >>> execfile('sync_virtual.py') From 595438785879552912a1a6832a4f2715f4e82272 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 16 Oct 2019 14:27:01 +1100 Subject: [PATCH 0589/1299] drivers/onewire/ds18x20.py: Add support for DS1822 sensor. DS1822P sensors behave just like the DS18B20 except for the following: - it has a different family code: 0x22 - it has only the GND and DQ pins connected, it uses parasitic power from the data line Contributed by @nebelgrau77. --- drivers/onewire/ds18x20.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/onewire/ds18x20.py b/drivers/onewire/ds18x20.py index bf0609483594a..272642239e43c 100644 --- a/drivers/onewire/ds18x20.py +++ b/drivers/onewire/ds18x20.py @@ -13,7 +13,7 @@ def __init__(self, onewire): self.buf = bytearray(9) def scan(self): - return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28] + return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)] def convert_temp(self): self.ow.reset(True) From 4f2c737b0c05cd138f15703d492ad64d39c3fcfd Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 16 Oct 2019 23:12:06 +1100 Subject: [PATCH 0590/1299] stm32/mpu: Save and restore the IRQ state when configuring MPU. In case IRQs are already disabled during the MPU configuration. Fixes issue #5152. --- ports/stm32/eth.c | 4 ++-- ports/stm32/mpu.h | 8 ++++---- ports/stm32/qspi.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ports/stm32/eth.c b/ports/stm32/eth.c index 9633d32b280a2..756bb6dd648b4 100644 --- a/ports/stm32/eth.c +++ b/ports/stm32/eth.c @@ -153,9 +153,9 @@ void eth_set_trace(eth_t *self, uint32_t value) { STATIC int eth_mac_init(eth_t *self) { // Configure MPU - mpu_config_start(); + uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_ETH, (uint32_t)ð_dma, MPU_CONFIG_ETH(MPU_REGION_SIZE_16KB)); - mpu_config_end(); + mpu_config_end(irq_state); // Configure GPIO mp_hal_pin_config_alt_static(MICROPY_HW_ETH_MDC, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, STATIC_AF_ETH_MDC); diff --git a/ports/stm32/mpu.h b/ports/stm32/mpu.h index 1efe93a68b6e0..74ba81496f94a 100644 --- a/ports/stm32/mpu.h +++ b/ports/stm32/mpu.h @@ -78,8 +78,8 @@ static inline void mpu_init(void) { __ISB(); } -static inline void mpu_config_start(void) { - __disable_irq(); +static inline uint32_t mpu_config_start(void) { + return disable_irq(); } static inline void mpu_config_region(uint32_t region, uint32_t base_addr, uint32_t attr_size) { @@ -88,11 +88,11 @@ static inline void mpu_config_region(uint32_t region, uint32_t base_addr, uint32 MPU->RASR = attr_size; } -static inline void mpu_config_end(void) { +static inline void mpu_config_end(uint32_t irq_state) { __ISB(); __DSB(); __DMB(); - __enable_irq(); + enable_irq(irq_state); } #else diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index ec744bfb27fc4..30ee2c9ea7aef 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -55,9 +55,9 @@ static inline void qspi_mpu_disable_all(void) { // Configure MPU to disable access to entire QSPI region, to prevent CPU // speculative execution from accessing this region and modifying QSPI registers. - mpu_config_start(); + uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x00, MPU_REGION_SIZE_256MB)); - mpu_config_end(); + mpu_config_end(irq_state); } static inline void qspi_mpu_enable_mapped(void) { @@ -67,11 +67,11 @@ static inline void qspi_mpu_enable_mapped(void) { // to everything except the valid address space, using holes in the bottom // of the regions and nesting them. // At the moment this is hard-coded to 2MiB of QSPI address space. - mpu_config_start(); + uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_QSPI1, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_256MB)); mpu_config_region(MPU_REGION_QSPI2, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x0f, MPU_REGION_SIZE_32MB)); mpu_config_region(MPU_REGION_QSPI3, QSPI_MAP_ADDR, MPU_CONFIG_DISABLE(0x01, MPU_REGION_SIZE_16MB)); - mpu_config_end(); + mpu_config_end(irq_state); } void qspi_init(void) { From 3105207afff2ec0b22ecbdea756be5bc5006daff Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 15 Oct 2019 22:42:18 +1100 Subject: [PATCH 0591/1299] stm32/accel: Rename MMA I2C macro constants to make it generic. --- ports/stm32/accel.c | 52 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index 73ddcf8cfabcf..b4916b5059d1f 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -48,13 +48,13 @@ #define I2C_TIMEOUT_MS (50) -#define MMA_ADDR (76) -#define MMA_REG_X (0) -#define MMA_REG_Y (1) -#define MMA_REG_Z (2) -#define MMA_REG_TILT (3) -#define MMA_REG_MODE (7) -#define MMA_AXIS_SIGNED_VALUE(i) (((i) & 0x3f) | ((i) & 0x20 ? (~0x1f) : 0)) +#define ACCEL_ADDR (76) +#define ACCEL_REG_X (0) +#define ACCEL_REG_Y (1) +#define ACCEL_REG_Z (2) +#define ACCEL_REG_TILT (3) +#define ACCEL_REG_MODE (7) +#define ACCEL_AXIS_SIGNED_VALUE(i) (((i) & 0x3f) | ((i) & 0x20 ? (~0x1f) : 0)) void accel_init(void) { // PB5 is connected to AVDD; pull high to enable MMA accel device @@ -74,7 +74,7 @@ STATIC void accel_start(void) { int ret; for (int i = 0; i < 4; i++) { - ret = i2c_writeto(I2C1, MMA_ADDR, NULL, 0, true); + ret = i2c_writeto(I2C1, ACCEL_ADDR, NULL, 0, true); if (ret == 0) { break; } @@ -85,8 +85,8 @@ STATIC void accel_start(void) { } // set MMA to active mode - uint8_t data[2] = {MMA_REG_MODE, 1}; // active mode - i2c_writeto(I2C1, MMA_ADDR, data, 2, true); + uint8_t data[2] = {ACCEL_REG_MODE, 1}; // active mode + i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); // wait for MMA to become active mp_hal_delay_ms(30); @@ -129,38 +129,38 @@ STATIC mp_obj_t pyb_accel_make_new(const mp_obj_type_t *type, size_t n_args, siz STATIC mp_obj_t read_axis(int axis) { uint8_t data[1] = { axis }; - i2c_writeto(I2C1, MMA_ADDR, data, 1, false); - i2c_readfrom(I2C1, MMA_ADDR, data, 1, true); - return mp_obj_new_int(MMA_AXIS_SIGNED_VALUE(data[0])); + i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); + i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); + return mp_obj_new_int(ACCEL_AXIS_SIGNED_VALUE(data[0])); } /// \method x() /// Get the x-axis value. STATIC mp_obj_t pyb_accel_x(mp_obj_t self_in) { - return read_axis(MMA_REG_X); + return read_axis(ACCEL_REG_X); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_x_obj, pyb_accel_x); /// \method y() /// Get the y-axis value. STATIC mp_obj_t pyb_accel_y(mp_obj_t self_in) { - return read_axis(MMA_REG_Y); + return read_axis(ACCEL_REG_Y); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_y_obj, pyb_accel_y); /// \method z() /// Get the z-axis value. STATIC mp_obj_t pyb_accel_z(mp_obj_t self_in) { - return read_axis(MMA_REG_Z); + return read_axis(ACCEL_REG_Z); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_z_obj, pyb_accel_z); /// \method tilt() /// Get the tilt register. STATIC mp_obj_t pyb_accel_tilt(mp_obj_t self_in) { - uint8_t data[1] = { MMA_REG_TILT }; - i2c_writeto(I2C1, MMA_ADDR, data, 1, false); - i2c_readfrom(I2C1, MMA_ADDR, data, 1, true); + uint8_t data[1] = { ACCEL_REG_TILT }; + i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); + i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); return mp_obj_new_int(data[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_tilt_obj, pyb_accel_tilt); @@ -172,13 +172,13 @@ STATIC mp_obj_t pyb_accel_filtered_xyz(mp_obj_t self_in) { memmove(self->buf, self->buf + NUM_AXIS, NUM_AXIS * (FILT_DEPTH - 1) * sizeof(int16_t)); - uint8_t data[NUM_AXIS] = { MMA_REG_X }; - i2c_writeto(I2C1, MMA_ADDR, data, 1, false); - i2c_readfrom(I2C1, MMA_ADDR, data, 3, true); + uint8_t data[NUM_AXIS] = { ACCEL_REG_X }; + i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); + i2c_readfrom(I2C1, ACCEL_ADDR, data, 3, true); mp_obj_t tuple[NUM_AXIS]; for (int i = 0; i < NUM_AXIS; i++) { - self->buf[NUM_AXIS * (FILT_DEPTH - 1) + i] = MMA_AXIS_SIGNED_VALUE(data[i]); + self->buf[NUM_AXIS * (FILT_DEPTH - 1) + i] = ACCEL_AXIS_SIGNED_VALUE(data[i]); int32_t val = 0; for (int j = 0; j < FILT_DEPTH; j++) { val += self->buf[i + NUM_AXIS * j]; @@ -192,15 +192,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_filtered_xyz_obj, pyb_accel_filtered_ STATIC mp_obj_t pyb_accel_read(mp_obj_t self_in, mp_obj_t reg) { uint8_t data[1] = { mp_obj_get_int(reg) }; - i2c_writeto(I2C1, MMA_ADDR, data, 1, false); - i2c_writeto(I2C1, MMA_ADDR, data, 1, true); + i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); + i2c_writeto(I2C1, ACCEL_ADDR, data, 1, true); return mp_obj_new_int(data[0]); } MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_read_obj, pyb_accel_read); STATIC mp_obj_t pyb_accel_write(mp_obj_t self_in, mp_obj_t reg, mp_obj_t val) { uint8_t data[2] = { mp_obj_get_int(reg), mp_obj_get_int(val) }; - i2c_writeto(I2C1, MMA_ADDR, data, 2, true); + i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(pyb_accel_write_obj, pyb_accel_write); From 28062b510835655b26fc387db7e9db770621586d Mon Sep 17 00:00:00 2001 From: "Frederic.Pierson" Date: Sat, 12 Oct 2019 12:38:23 +0200 Subject: [PATCH 0592/1299] stm32/accel: Add support for KXTJ3. --- ports/stm32/accel.c | 76 ++++++++++++++++++++++++++++++++++++++++---- ports/stm32/modpyb.c | 2 +- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index b4916b5059d1f..634ed0a752aa7 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -33,21 +33,30 @@ #include "i2c.h" #include "accel.h" -#if MICROPY_HW_HAS_MMA7660 +#if MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 /// \moduleref pyb /// \class Accel - accelerometer control /// -/// Accel is an object that controls the accelerometer. Example usage: +/// Accel is an object that controls the MMA7660 or the KXTJ3 accelerometer +/// depending on one/two constant in mpconfigboard.h file of board project : +/// #define MICROPY_HW_HAS_MMA7660 (1) +/// #define MICROPY_HW_HAS_KXTJ3 (0) // not mandatory if equal to 0 +/// +/// Example usage: /// /// accel = pyb.Accel() /// for i in range(10): /// print(accel.x(), accel.y(), accel.z()) /// -/// Raw values are between -32 and 31. +/// Raw values are between -32 and 31 for -/+ 1.5G acceleration for MMA7660. +/// Raw values are between -128 and 127 for -/+ 8G acceleration for KXTJ3. + #define I2C_TIMEOUT_MS (50) +#if MICROPY_HW_HAS_MMA7660 + #define ACCEL_ADDR (76) #define ACCEL_REG_X (0) #define ACCEL_REG_Y (1) @@ -56,16 +65,36 @@ #define ACCEL_REG_MODE (7) #define ACCEL_AXIS_SIGNED_VALUE(i) (((i) & 0x3f) | ((i) & 0x20 ? (~0x1f) : 0)) +#elif MICROPY_HW_HAS_KXTJ3 + +#define ACCEL_ADDR (0x0f) +#define ACCEL_REG_DCST_RESP (0x0c) +#define ACCEL_REG_WHO_AM_I (0x0f) +#define ACCEL_REG_X (0x07) // XOUT_H +#define ACCEL_REG_Y (0x09) // YOUT_H +#define ACCEL_REG_Z (0x0B) // ZOUT_H +#define ACCEL_REG_CTRL_REG1 (0x1B) +#define ACCEL_REG_CTRL_REG2 (0x1d) +#define ACCEL_REG_CTRL_REG2 (0x1d) +#define ACCEL_REG_DATA_CTRL_REG (0x21) +#define ACCEL_AXIS_SIGNED_VALUE(i) (((i) & 0x7f) | ((i) & 0x80 ? (~0x7f) : 0)) + +#endif + void accel_init(void) { + #if MICROPY_HW_HAS_MMA7660 // PB5 is connected to AVDD; pull high to enable MMA accel device mp_hal_pin_low(MICROPY_HW_MMA_AVDD_PIN); // turn off AVDD mp_hal_pin_output(MICROPY_HW_MMA_AVDD_PIN); + #endif } STATIC void accel_start(void) { // start the I2C bus in master mode i2c_init(I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 400000, I2C_TIMEOUT_MS); + #if MICROPY_HW_HAS_MMA7660 + // turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again mp_hal_pin_low(MICROPY_HW_MMA_AVDD_PIN); // turn off mp_hal_delay_ms(30); @@ -90,6 +119,27 @@ STATIC void accel_start(void) { // wait for MMA to become active mp_hal_delay_ms(30); + + #elif MICROPY_HW_HAS_KXTJ3 + + // readout WHO_AM_I register to check KXTJ3 device presence + uint8_t data[2] = { ACCEL_REG_WHO_AM_I }; + i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); + i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); + if (data[0] != 0x35) { + mp_raise_msg(&mp_type_OSError, "accelerometer not found"); + } + + // set operating mode (default: 8 bits, range +/-8G) + data[0] = ACCEL_REG_CTRL_REG1; + data[1] = 0x90; + i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); + // set dat output rates to 200Hz (LPF roll-over 10ms), idd=35uA + data[0] = ACCEL_REG_DATA_CTRL_REG; + data[1] = 0x04; + i2c_writeto(I2C1, ACCEL_ADDR, data, 2, true); + + #endif } /******************************************************************************/ @@ -158,10 +208,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_z_obj, pyb_accel_z); /// \method tilt() /// Get the tilt register. STATIC mp_obj_t pyb_accel_tilt(mp_obj_t self_in) { + #if MICROPY_HW_HAS_MMA7660 uint8_t data[1] = { ACCEL_REG_TILT }; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); return mp_obj_new_int(data[0]); + #elif MICROPY_HW_HAS_KXTJ3 + /// No tilt like register with KXTJ3 accelerometer + return 0; + #endif } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_tilt_obj, pyb_accel_tilt); @@ -172,13 +227,20 @@ STATIC mp_obj_t pyb_accel_filtered_xyz(mp_obj_t self_in) { memmove(self->buf, self->buf + NUM_AXIS, NUM_AXIS * (FILT_DEPTH - 1) * sizeof(int16_t)); - uint8_t data[NUM_AXIS] = { ACCEL_REG_X }; + #if MICROPY_HW_HAS_MMA7660 + const size_t DATA_SIZE = NUM_AXIS; + const size_t DATA_STRIDE = 1; + #elif MICROPY_HW_HAS_KXTJ3 + const size_t DATA_SIZE = 5; + const size_t DATA_STRIDE = 2; + #endif + uint8_t data[DATA_SIZE]; data[0] = ACCEL_REG_X; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); - i2c_readfrom(I2C1, ACCEL_ADDR, data, 3, true); + i2c_readfrom(I2C1, ACCEL_ADDR, data, DATA_SIZE, true); mp_obj_t tuple[NUM_AXIS]; for (int i = 0; i < NUM_AXIS; i++) { - self->buf[NUM_AXIS * (FILT_DEPTH - 1) + i] = ACCEL_AXIS_SIGNED_VALUE(data[i]); + self->buf[NUM_AXIS * (FILT_DEPTH - 1) + i] = ACCEL_AXIS_SIGNED_VALUE(data[i * DATA_STRIDE]); int32_t val = 0; for (int j = 0; j < FILT_DEPTH; j++) { val += self->buf[i + NUM_AXIS * j]; @@ -225,4 +287,4 @@ const mp_obj_type_t pyb_accel_type = { .locals_dict = (mp_obj_dict_t*)&pyb_accel_locals_dict, }; -#endif // MICROPY_HW_HAS_MMA7660 +#endif // MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index 1a1f567a5f670..71d7849233293 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -248,7 +248,7 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&pyb_dac_type) }, #endif -#if MICROPY_HW_HAS_MMA7660 +#if MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3 { MP_ROM_QSTR(MP_QSTR_Accel), MP_ROM_PTR(&pyb_accel_type) }, #endif From 925f244ab39d52901b402695a9a8b0bfce6415f7 Mon Sep 17 00:00:00 2001 From: "Frederic.Pierson" Date: Thu, 19 Sep 2019 18:14:55 +0200 Subject: [PATCH 0593/1299] stm32/boards: Add NADHAT_PYB405 board. --- .../boards/NADHAT_PYBF405/mpconfigboard.h | 105 ++++++++++++++++++ .../boards/NADHAT_PYBF405/mpconfigboard.mk | 13 +++ ports/stm32/boards/NADHAT_PYBF405/pins.csv | 58 ++++++++++ .../NADHAT_PYBF405/stm32f4xx_hal_conf.h | 19 ++++ 4 files changed, 195 insertions(+) create mode 100644 ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h create mode 100644 ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.mk create mode 100644 ports/stm32/boards/NADHAT_PYBF405/pins.csv create mode 100644 ports/stm32/boards/NADHAT_PYBF405/stm32f4xx_hal_conf.h diff --git a/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h b/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h new file mode 100644 index 0000000000000..c6f1a7bc6eb2b --- /dev/null +++ b/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.h @@ -0,0 +1,105 @@ +#define MICROPY_HW_BOARD_NAME "NADHAT_PYBF405" +#define MICROPY_HW_MCU_NAME "STM32F405RG" + +#define MICROPY_HW_HAS_SWITCH (1) +#define MICROPY_HW_HAS_FLASH (1) +#define MICROPY_HW_HAS_KXTJ3 (1) +#define MICROPY_HW_HAS_LCD (1) +#define MICROPY_HW_ENABLE_RNG (1) +#define MICROPY_HW_ENABLE_RTC (1) +#define MICROPY_HW_ENABLE_SERVO (1) +#define MICROPY_HW_ENABLE_DAC (1) +#define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_ENABLE_SDCARD (1) + +// HSE is 16MHz +#define MICROPY_HW_CLK_PLLM (16) +#define MICROPY_HW_CLK_PLLN (336) +#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) +#define MICROPY_HW_CLK_PLLQ (7) +#define MICROPY_HW_CLK_LAST_FREQ (1) + +// The board has a 32kHz crystal for the RTC +#define MICROPY_HW_RTC_USE_LSE (1) +#define MICROPY_HW_RTC_USE_US (0) +#define MICROPY_HW_RTC_USE_CALOUT (1) + +// UART config +#define MICROPY_HW_UART1_NAME "XB" +#define MICROPY_HW_UART1_TX (pin_B6) +#define MICROPY_HW_UART1_RX (pin_B7) +#define MICROPY_HW_UART2_TX (pin_A2) +#define MICROPY_HW_UART2_RX (pin_A3) +#define MICROPY_HW_UART2_RTS (pin_A1) +#define MICROPY_HW_UART2_CTS (pin_A0) +#define MICROPY_HW_UART3_NAME "YB" +#define MICROPY_HW_UART3_TX (pin_B10) +#define MICROPY_HW_UART3_RX (pin_B11) +#define MICROPY_HW_UART3_RTS (pin_B14) +#define MICROPY_HW_UART3_CTS (pin_B13) +#define MICROPY_HW_UART4_NAME "XA" +#define MICROPY_HW_UART4_TX (pin_A0) +#define MICROPY_HW_UART4_RX (pin_A1) +#define MICROPY_HW_UART6_NAME "YA" +#define MICROPY_HW_UART6_TX (pin_C6) +#define MICROPY_HW_UART6_RX (pin_C7) + +// I2C buses +#define MICROPY_HW_I2C1_NAME "X" +#define MICROPY_HW_I2C1_SCL (pin_B6) +#define MICROPY_HW_I2C1_SDA (pin_B7) +#define MICROPY_HW_I2C2_NAME "Y" +#define MICROPY_HW_I2C2_SCL (pin_B10) +#define MICROPY_HW_I2C2_SDA (pin_B11) + +// SPI buses +#define MICROPY_HW_SPI1_NAME "X" +#define MICROPY_HW_SPI1_NSS (pin_A4) // X5 +#define MICROPY_HW_SPI1_SCK (pin_A5) // X6 +#define MICROPY_HW_SPI1_MISO (pin_A6) // X7 +#define MICROPY_HW_SPI1_MOSI (pin_A7) // X8 +#define MICROPY_HW_SPI2_NAME "Y" +#define MICROPY_HW_SPI2_NSS (pin_B12) // Y5 +#define MICROPY_HW_SPI2_SCK (pin_B13) // Y6 +#define MICROPY_HW_SPI2_MISO (pin_B14) // Y7 +#define MICROPY_HW_SPI2_MOSI (pin_B15) // Y8 + +// CAN buses +#define MICROPY_HW_CAN1_NAME "YA" +#define MICROPY_HW_CAN1_TX (pin_B9) // Y4 +#define MICROPY_HW_CAN1_RX (pin_B8) // Y3 +#define MICROPY_HW_CAN2_NAME "YB" +#define MICROPY_HW_CAN2_TX (pin_B13) // Y6 +#define MICROPY_HW_CAN2_RX (pin_B12) // Y5 + +// USRSW has no pullup or pulldown, and pressing the switch makes the input go low +#define MICROPY_HW_USRSW_PIN (pin_B3) +#define MICROPY_HW_USRSW_PULL (GPIO_PULLUP) +#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING) +#define MICROPY_HW_USRSW_PRESSED (0) + +// The board has 4 LEDs +#define MICROPY_HW_LED1 (pin_A13) // red +#define MICROPY_HW_LED2 (pin_A14) // green +#define MICROPY_HW_LED3 (pin_A15) // yellow +#define MICROPY_HW_LED4 (pin_B4) // blue +#define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } +#define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) + +// SD card detect switch +#define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) +#define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) +#define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) + +// USB config +#define MICROPY_HW_USB_FS (1) +#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) +#define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) + +// Bootloader configuration (only needed if Mboot is used) +#define MBOOT_I2C_PERIPH_ID 1 +#define MBOOT_I2C_SCL (pin_B8) +#define MBOOT_I2C_SDA (pin_B9) +#define MBOOT_I2C_ALTFUNC (4) diff --git a/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.mk b/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.mk new file mode 100644 index 0000000000000..a4430cc1df0e4 --- /dev/null +++ b/ports/stm32/boards/NADHAT_PYBF405/mpconfigboard.mk @@ -0,0 +1,13 @@ +MCU_SERIES = f4 +CMSIS_MCU = STM32F405xx +AF_FILE = boards/stm32f405_af.csv +ifeq ($(USE_MBOOT),1) +# When using Mboot all the text goes together after the filesystem +LD_FILES = boards/stm32f405.ld boards/common_blifs.ld +TEXT0_ADDR = 0x08020000 +else +# When not using Mboot the ISR text goes first, then the rest after the filesystem +LD_FILES = boards/stm32f405.ld boards/common_ifs.ld +TEXT0_ADDR = 0x08000000 +TEXT1_ADDR = 0x08020000 +endif diff --git a/ports/stm32/boards/NADHAT_PYBF405/pins.csv b/ports/stm32/boards/NADHAT_PYBF405/pins.csv new file mode 100644 index 0000000000000..0a030e985c275 --- /dev/null +++ b/ports/stm32/boards/NADHAT_PYBF405/pins.csv @@ -0,0 +1,58 @@ +X1,PA0 +X2,PA1 +X3,PA2 +X4,PA3 +X5,PA4 +X6,PA5 +X7,PA6 +X8,PA7 +X9,PB6 +X10,PB7 +X11,PC4 +X12,PC5 +X13,Reset +X14,GND +X15,3.3V +X16,VIN +X17,PB3 +X18,PC13 +X19,PC0 +X20,PC1 +X21,PC2 +X22,PC3 +X23,A3.3V +X24,AGND +Y1,PC6 +Y2,PC7 +Y3,PB8 +Y4,PB9 +Y5,PB12 +Y6,PB13 +Y7,PB14 +Y8,PB15 +Y9,PB10 +Y10,PB11 +Y11,PB0 +Y12,PB1 +Y13,PB2 +Y14,GND +Y15,3.3V +Y16,VIN +SW,PB3 +LED_RED,PA13 +LED_GREEN,PA14 +LED_YELLOW,PA15 +LED_BLUE,PB4 +NC,PB5 +SD_D0,PC8 +SD_D1,PC9 +SD_D2,PC10 +SD_D3,PC11 +SD_CMD,PD2 +SD_CK,PC12 +SD,PA8 +SD_SW,PA8 +USB_VBUS,PA9 +USB_ID,PA10 +USB_DM,PA11 +USB_DP,PA12 diff --git a/ports/stm32/boards/NADHAT_PYBF405/stm32f4xx_hal_conf.h b/ports/stm32/boards/NADHAT_PYBF405/stm32f4xx_hal_conf.h new file mode 100644 index 0000000000000..7d6344f0a2453 --- /dev/null +++ b/ports/stm32/boards/NADHAT_PYBF405/stm32f4xx_hal_conf.h @@ -0,0 +1,19 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2019 Damien P. George + */ +#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H +#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H + +#include "boards/stm32f4xx_hal_conf_base.h" + +// Oscillator values in Hz +#define HSE_VALUE (16000000) +#define LSE_VALUE (32768) +#define EXTERNAL_CLOCK_VALUE (12288000) + +// Oscillator timeouts in ms +#define HSE_STARTUP_TIMEOUT (100) +#define LSE_STARTUP_TIMEOUT (5000) + +#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H From 69b238ec63b808429b1495516a62fd56a9faf764 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 11:53:34 +1100 Subject: [PATCH 0594/1299] stm32/accel: Fix Accel.read() method so it does read a byte. This bug was introduced in a0f7b4c678829bf252df58f0153351a44bd95059 --- ports/stm32/accel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c index 634ed0a752aa7..eb55b5d012a39 100644 --- a/ports/stm32/accel.c +++ b/ports/stm32/accel.c @@ -255,7 +255,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_filtered_xyz_obj, pyb_accel_filtered_ STATIC mp_obj_t pyb_accel_read(mp_obj_t self_in, mp_obj_t reg) { uint8_t data[1] = { mp_obj_get_int(reg) }; i2c_writeto(I2C1, ACCEL_ADDR, data, 1, false); - i2c_writeto(I2C1, ACCEL_ADDR, data, 1, true); + i2c_readfrom(I2C1, ACCEL_ADDR, data, 1, true); return mp_obj_new_int(data[0]); } MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_read_obj, pyb_accel_read); From 7a7ee16ccf51d4218c17628e745228316f0151f0 Mon Sep 17 00:00:00 2001 From: Jeremy Herbert Date: Thu, 10 Oct 2019 05:11:01 -0700 Subject: [PATCH 0595/1299] esp32/machine_uart: Add ability to invert UART pins. --- ports/esp32/machine_uart.c | 47 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c index 38cc1a8a9ac72..352ef32a78e77 100644 --- a/ports/esp32/machine_uart.c +++ b/ports/esp32/machine_uart.c @@ -50,6 +50,7 @@ typedef struct _machine_uart_obj_t { uint16_t rxbuf; uint16_t timeout; // timeout waiting for first char (in ms) uint16_t timeout_char; // timeout waiting between chars (in ms) + uint32_t invert; // lines to invert } machine_uart_obj_t; STATIC const char *_parity_name[] = {"None", "1", "0"}; @@ -61,13 +62,42 @@ STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_pri machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); uint32_t baudrate; uart_get_baudrate(self->uart_num, &baudrate); - mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, rts=%d, cts=%d, txbuf=%u, rxbuf=%u, timeout=%u, timeout_char=%u)", + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, rts=%d, cts=%d, txbuf=%u, rxbuf=%u, timeout=%u, timeout_char=%u", self->uart_num, baudrate, self->bits, _parity_name[self->parity], self->stop, self->tx, self->rx, self->rts, self->cts, self->txbuf, self->rxbuf, self->timeout, self->timeout_char); + if (self->invert) { + mp_printf(print, ", invert="); + uint32_t invert_mask = self->invert; + if (invert_mask & UART_INVERSE_TXD) { + mp_printf(print, "INV_TX"); + invert_mask &= ~UART_INVERSE_TXD; + if (invert_mask) { + mp_printf(print, "|"); + } + } + if (invert_mask & UART_INVERSE_RXD) { + mp_printf(print, "INV_RX"); + invert_mask &= ~UART_INVERSE_RXD; + if (invert_mask) { + mp_printf(print, "|"); + } + } + if (invert_mask & UART_INVERSE_RTS) { + mp_printf(print, "INV_RTS"); + invert_mask &= ~UART_INVERSE_RTS; + if (invert_mask) { + mp_printf(print, "|"); + } + } + if (invert_mask & UART_INVERSE_CTS) { + mp_printf(print, "INV_CTS"); + } + } + mp_printf(print, ")"); } STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char }; + enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_txbuf, ARG_rxbuf, ARG_timeout, ARG_timeout_char, ARG_invert }; static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} }, @@ -81,6 +111,7 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -205,6 +236,13 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co if (self->timeout_char < min_timeout_char) { self->timeout_char = min_timeout_char; } + + // set line inversion + if (args[ARG_invert].u_int & ~UART_LINE_INV_MASK) { + mp_raise_ValueError("invalid inversion mask"); + } + self->invert = args[ARG_invert].u_int; + uart_set_line_inverse(self->uart_num, self->invert); } STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { @@ -341,6 +379,11 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) }, + + { MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERSE_TXD) }, + { MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERSE_RXD) }, + { MP_ROM_QSTR(MP_QSTR_INV_RTS), MP_ROM_INT(UART_INVERSE_RTS) }, + { MP_ROM_QSTR(MP_QSTR_INV_CTS), MP_ROM_INT(UART_INVERSE_CTS) }, }; STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); From ebf8332104c1c6fbd01b521a713e49d040c62920 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 16 Oct 2019 16:56:29 +1100 Subject: [PATCH 0596/1299] extmod/re1.5: Support escaping within RE classes. Fixes issues #3178 and #5220. Tests are added, including all the cases mentioned in both bugs. --- extmod/re1.5/compilecode.c | 3 +++ tests/extmod/ure1.py | 20 ++++++++++++++++++++ tests/extmod/ure_error.py | 1 + 3 files changed, 24 insertions(+) diff --git a/extmod/re1.5/compilecode.c b/extmod/re1.5/compilecode.c index a685a508a04b3..3f54b3993fd36 100644 --- a/extmod/re1.5/compilecode.c +++ b/extmod/re1.5/compilecode.c @@ -53,6 +53,9 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) PC++; // Skip # of pair byte prog->len++; for (cnt = 0; *re != ']'; re++, cnt++) { + if (*re == '\\') { + ++re; + } if (!*re) return NULL; EMIT(PC++, *re); if (re[1] == '-' && re[2] != ']') { diff --git a/tests/extmod/ure1.py b/tests/extmod/ure1.py index 54471ed4f97c4..ae9ff34703b68 100644 --- a/tests/extmod/ure1.py +++ b/tests/extmod/ure1.py @@ -88,3 +88,23 @@ # bytes objects m = re.match(rb'a+?', b'ab'); print(m.group(0)) +print("===") + +# escaping +m = re.match(r'a\.c', 'a.c'); print(m.group(0) if m else '') +m = re.match(r'a\.b', 'abc'); print(m is None) +m = re.match(r'a\.b', 'a\\bc'); print(m is None) +m = re.match(r'[a\-z]', 'abc'); print(m.group(0)) +m = re.match(r'[.\]]*', '.].]a'); print(m.group(0)) +m = re.match(r'[.\]+]*', '.]+.]a'); print(m.group(0)) +m = re.match(r'[a-f0-9x\-yz]*', 'abxcd1-23'); print(m.group(0)) +m = re.match(r'[a\\b]*', 'a\\aa\\bb\\bbab'); print(m.group(0)) +m = re.search(r'[a\-z]', '-'); print(m.group(0)) +m = re.search(r'[a\-z]', 'f'); print(m is None) +m = re.search(r'[a\]z]', 'a'); print(m.group(0)) +print(re.compile(r'[-a]').split('foo-bar')) +print(re.compile(r'[a-]').split('foo-bar')) +print(re.compile(r'[ax\-]').split('foo-bar')) +print(re.compile(r'[a\-x]').split('foo-bar')) +print(re.compile(r'[\-ax]').split('foo-bar')) +print("===") diff --git a/tests/extmod/ure_error.py b/tests/extmod/ure_error.py index f52f735c7fa5e..02d48d2a838b8 100644 --- a/tests/extmod/ure_error.py +++ b/tests/extmod/ure_error.py @@ -23,3 +23,4 @@ def test_re(r): test_re(r'[') test_re(r'([') test_re(r'([)') +test_re(r'[a\]') From 25a228af7e5809fe3a582f665c13a2d38eb5ed40 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 15 Oct 2019 17:45:21 +1100 Subject: [PATCH 0597/1299] examples/bluetooth: Add basic BLE peripheral examples. Consisting of: - ble_advertising.py -- helper to generate advertising payload. - ble_temperature.py -- simple temperature device. - ble_uart_periperhal.py -- BLE UART wrapper. - ble_uart_repl.py -- dupterm-compatible uart. --- examples/bluetooth/ble_advertising.py | 37 +++++++++++ examples/bluetooth/ble_temperature.py | 76 +++++++++++++++++++++ examples/bluetooth/ble_uart_peripheral.py | 78 ++++++++++++++++++++++ examples/bluetooth/ble_uart_repl.py | 80 +++++++++++++++++++++++ 4 files changed, 271 insertions(+) create mode 100644 examples/bluetooth/ble_advertising.py create mode 100644 examples/bluetooth/ble_temperature.py create mode 100644 examples/bluetooth/ble_uart_peripheral.py create mode 100644 examples/bluetooth/ble_uart_repl.py diff --git a/examples/bluetooth/ble_advertising.py b/examples/bluetooth/ble_advertising.py new file mode 100644 index 0000000000000..f52598a62a54f --- /dev/null +++ b/examples/bluetooth/ble_advertising.py @@ -0,0 +1,37 @@ +# Helpers for generating BLE advertising payloads. + +from micropython import const +import struct + +# Advertising payloads are repeated packets of the following form: +# 1 byte data length (N + 1) +# 1 byte type (see constants below) +# N bytes type-specific data + +_ADV_TYPE_FLAGS = const(0x01) +_ADV_TYPE_NAME = const(0x09) +_ADV_TYPE_UUID16_COMPLETE = const(0x3) +_ADV_TYPE_APPEARANCE = const(0x19) + +# Generate a payload to be passed to gap_advertise(adv_data=...). +def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): + payload = bytearray() + + def _append(adv_type, value): + nonlocal payload + payload += struct.pack('BB', len(value) + 1, adv_type) + value + + _append(_ADV_TYPE_FLAGS, struct.pack('B', (0x01 if limited_disc else 0x02) + (0x00 if br_edr else 0x04))) + + if name: + _append(_ADV_TYPE_NAME, name) + + if services: + for uuid in services: + # TODO: Support bluetooth.UUID class. + _append(_ADV_TYPE_UUID16_COMPLETE, struct.pack(' Date: Fri, 11 Oct 2019 10:52:07 +1300 Subject: [PATCH 0598/1299] esp32/boards: Split out CPU frequency config, make 160MHz the default. Remove the 240MHz CPU config option from sdkconfig.base and create a new sdkconfig.240mhz file for those boards that want to use 240MHz on boot. The default CPU frequency is now 160MHz (was 240MHz), to align with the ESP IDF and support more boards (eg those with D2WD chips). Fixes issue #5169. --- ports/esp32/boards/TINYPICO/mpconfigboard.mk | 1 + ports/esp32/boards/sdkconfig.240mhz | 5 +++++ ports/esp32/boards/sdkconfig.base | 1 - 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 ports/esp32/boards/sdkconfig.240mhz diff --git a/ports/esp32/boards/TINYPICO/mpconfigboard.mk b/ports/esp32/boards/TINYPICO/mpconfigboard.mk index 2efdba0f39d9f..485b3f16564d0 100644 --- a/ports/esp32/boards/TINYPICO/mpconfigboard.mk +++ b/ports/esp32/boards/TINYPICO/mpconfigboard.mk @@ -1,5 +1,6 @@ FLASH_FREQ = 80m SDKCONFIG += boards/sdkconfig.base +SDKCONFIG += boards/sdkconfig.240mhz SDKCONFIG += boards/sdkconfig.spiram SDKCONFIG += boards/TINYPICO/sdkconfig.board diff --git a/ports/esp32/boards/sdkconfig.240mhz b/ports/esp32/boards/sdkconfig.240mhz new file mode 100644 index 0000000000000..a0cb113a48027 --- /dev/null +++ b/ports/esp32/boards/sdkconfig.240mhz @@ -0,0 +1,5 @@ +# MicroPython on ESP32, ESP IDF configuration with 240MHz CPU +CONFIG_ESP32_DEFAULT_CPU_FREQ_80= +CONFIG_ESP32_DEFAULT_CPU_FREQ_160= +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 \ No newline at end of file diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index a11c9397f60ac..9348f406324d8 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -11,7 +11,6 @@ CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR=y CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y # ESP32-specific -CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n CONFIG_ESP32_XTAL_FREQ_AUTO=y From 8f9e2e325ab0d0dfa9457779010a4cb2cfe60fef Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Tue, 24 Sep 2019 17:01:54 +1200 Subject: [PATCH 0599/1299] py/objtype: Add type.__bases__ attribute. Enabled as part of MICROPY_CPYTHON_COMPAT. --- py/objtype.c | 15 +++++++++++++ tests/basics/class_bases.py | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tests/basics/class_bases.py diff --git a/py/objtype.c b/py/objtype.c index 236c79e6ad415..bf089dc490db9 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1014,6 +1014,21 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[0] = MP_OBJ_NEW_QSTR(self->name); return; } + if (attr == MP_QSTR___bases__) { + if (self == &mp_type_object) { + dest[0] = mp_const_empty_tuple; + return; + } + mp_obj_t parent_obj = self->parent ? MP_OBJ_FROM_PTR(self->parent) : MP_OBJ_FROM_PTR(&mp_type_object); + #if MICROPY_MULTIPLE_INHERITANCE + if (mp_obj_is_type(parent_obj, &mp_type_tuple)) { + dest[0] = parent_obj; + return; + } + #endif + dest[0] = mp_obj_new_tuple(1, &parent_obj); + return; + } #endif struct class_lookup_data lookup = { .obj = (mp_obj_instance_t*)self, diff --git a/tests/basics/class_bases.py b/tests/basics/class_bases.py new file mode 100644 index 0000000000000..d3cf4f598a553 --- /dev/null +++ b/tests/basics/class_bases.py @@ -0,0 +1,45 @@ +# test for type.__bases__ implementation + +if not hasattr(object, '__bases__'): + print("SKIP") + raise SystemExit + +class A: + pass + +class B(object): + pass + +class C(B): + pass + +class D(C, A): + pass + +# Check the attribute exists +print(hasattr(A, '__bases__')) +print(hasattr(B, '__bases__')) +print(hasattr(C, '__bases__')) +print(hasattr(D, '__bases__')) + +# Check it is always a tuple +print(type(A.__bases__) == tuple) +print(type(B.__bases__) == tuple) +print(type(C.__bases__) == tuple) +print(type(D.__bases__) == tuple) + +# Check size +print(len(A.__bases__) == 1) +print(len(B.__bases__) == 1) +print(len(C.__bases__) == 1) +print(len(D.__bases__) == 2) + +# Check values +print(A.__bases__[0] == object) +print(B.__bases__[0] == object) +print(C.__bases__[0] == B) +print(D.__bases__[0] == C) +print(D.__bases__[1] == A) + +# Object has an empty tuple +print(object.__bases__ == tuple()) From 12413e92a3f938bdfe844bd65bf189ee1431e1d0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 21 Oct 2019 12:23:41 +1100 Subject: [PATCH 0600/1299] stm32/powerctrlboot: Fix config of systick IRQ priority on F0/L0/WB MCU. Prior to this commit the systick IRQ priority was set at lowest priority on F0/L0/WB MCUs, because it was left at the default and never configured. This commit ensures the priority is configured and sets it to the highest priority. --- ports/stm32/irq.h | 4 ++-- ports/stm32/powerctrlboot.c | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ports/stm32/irq.h b/ports/stm32/irq.h index 78ba46ced4651..4b1251666c202 100644 --- a/ports/stm32/irq.h +++ b/ports/stm32/irq.h @@ -120,7 +120,7 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj); #if __CORTEX_M == 0 -//#def IRQ_PRI_SYSTICK 0 +#define IRQ_PRI_SYSTICK 0 #define IRQ_PRI_UART 1 #define IRQ_PRI_SDIO 1 #define IRQ_PRI_DMA 1 @@ -136,7 +136,7 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj); #else -//#def IRQ_PRI_SYSTICK NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 0, 0) +#define IRQ_PRI_SYSTICK NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 0, 0) // The UARTs have no FIFOs, so if they don't get serviced quickly then characters // get dropped. The handling for each character only consumes about 0.5 usec diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 766c52dfb1a61..acc33f1259b3c 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -27,6 +27,13 @@ #include "py/mphal.h" #include "powerctrl.h" +static inline void powerctrl_config_systick(void) { + // Configure SYSTICK to run at 1kHz (1ms interval) + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + SysTick_Config(HAL_RCC_GetHCLKFreq() / 1000); + NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_SYSTICK); +} + #if defined(STM32F0) void SystemClock_Config(void) { @@ -88,9 +95,7 @@ void SystemClock_Config(void) { } SystemCoreClockUpdate(); - - HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + powerctrl_config_systick(); } #elif defined(STM32L0) @@ -122,9 +127,7 @@ void SystemClock_Config(void) { } SystemCoreClockUpdate(); - - HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + powerctrl_config_systick(); #if MICROPY_HW_ENABLE_RNG || MICROPY_HW_ENABLE_USB // Enable the 48MHz internal oscillator @@ -189,9 +192,7 @@ void SystemClock_Config(void) { RCC->CCIPR = 2 << RCC_CCIPR_CLK48SEL_Pos; SystemCoreClockUpdate(); - - HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + powerctrl_config_systick(); } #endif From 8ba963cfa3da8e712e94c2429cfd6f064b1b4c69 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 16 Oct 2019 15:12:39 +1100 Subject: [PATCH 0601/1299] tools/makemanifest.py: Eval relative paths w.r.t. current manifest file. When loading a manifest file, e.g. by include(), it will chdir first to the directory of that manifest. This means that all file operations within a manifest are relative to that manifest's location. As a consequence of this, additional environment variables are needed to find absolute paths, so the following are added: $(MPY_LIB_DIR), $(PORT_DIR), $(BOARD_DIR). And rename $(MPY) to $(MPY_DIR) to be consistent. Existing manifests are updated to match. --- ports/esp32/boards/manifest.py | 12 ++-- ports/esp32/boards/manifest_release.py | 12 ++-- ports/esp8266/boards/manifest.py | 8 +-- ports/stm32/boards/manifest.py | 6 +- ports/unix/manifest.py | 4 +- py/mkenv.mk | 2 + py/mkrules.mk | 2 +- tools/makemanifest.py | 83 +++++++++++++++++++------- 8 files changed, 85 insertions(+), 44 deletions(-) diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py index 3da8af57f8b46..2b07639ee9090 100644 --- a/ports/esp32/boards/manifest.py +++ b/ports/esp32/boards/manifest.py @@ -1,6 +1,6 @@ -freeze('modules') -freeze('$(MPY)/tools', ('upip.py', 'upip_utarfile.py')) -freeze('$(MPY)/ports/esp8266/modules', 'ntptime.py') -freeze('$(MPY)/ports/esp8266/modules', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) -freeze('$(MPY)/drivers/dht', 'dht.py') -freeze('$(MPY)/drivers/onewire') +freeze('$(PORT_DIR)/modules') +freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) +freeze('$(MPY_DIR)/ports/esp8266/modules', 'ntptime.py') +freeze('$(MPY_DIR)/ports/esp8266/modules', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) +freeze('$(MPY_DIR)/drivers/dht', 'dht.py') +freeze('$(MPY_DIR)/drivers/onewire') diff --git a/ports/esp32/boards/manifest_release.py b/ports/esp32/boards/manifest_release.py index e56704d023453..9c898af26d748 100644 --- a/ports/esp32/boards/manifest_release.py +++ b/ports/esp32/boards/manifest_release.py @@ -1,8 +1,6 @@ -include('boards/manifest.py') +include('manifest.py') -LIB = '../../../micropython-lib' - -freeze(LIB + '/upysh', 'upysh.py') -freeze(LIB + '/urequests', 'urequests.py') -freeze(LIB + '/umqtt.simple', 'umqtt/simple.py') -freeze(LIB + '/umqtt.robust', 'umqtt/robust.py') +freeze('$(MPY_LIB_DIR)/upysh', 'upysh.py') +freeze('$(MPY_LIB_DIR)/urequests', 'urequests.py') +freeze('$(MPY_LIB_DIR)/umqtt.simple', 'umqtt/simple.py') +freeze('$(MPY_LIB_DIR)/umqtt.robust', 'umqtt/robust.py') diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py index 1264a2268627e..779e840880064 100644 --- a/ports/esp8266/boards/manifest.py +++ b/ports/esp8266/boards/manifest.py @@ -1,4 +1,4 @@ -freeze('modules') -freeze('$(MPY)/tools', ('upip.py', 'upip_utarfile.py')) -freeze('$(MPY)/drivers/dht', 'dht.py') -freeze('$(MPY)/drivers/onewire') +freeze('$(PORT_DIR)/modules') +freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) +freeze('$(MPY_DIR)/drivers/dht', 'dht.py') +freeze('$(MPY_DIR)/drivers/onewire') diff --git a/ports/stm32/boards/manifest.py b/ports/stm32/boards/manifest.py index 99b08cca00c4c..41b728fa28498 100644 --- a/ports/stm32/boards/manifest.py +++ b/ports/stm32/boards/manifest.py @@ -1,3 +1,3 @@ -freeze('$(MPY)/drivers/dht', 'dht.py') -freeze('$(MPY)/drivers/display', ('lcd160cr.py', 'lcd160cr_test.py')) -freeze('$(MPY)/drivers/onewire', 'onewire.py') +freeze('$(MPY_DIR)/drivers/dht', 'dht.py') +freeze('$(MPY_DIR)/drivers/display', ('lcd160cr.py', 'lcd160cr_test.py')) +freeze('$(MPY_DIR)/drivers/onewire', 'onewire.py') diff --git a/ports/unix/manifest.py b/ports/unix/manifest.py index 3f332446d1ac2..666b4c0ab3eee 100644 --- a/ports/unix/manifest.py +++ b/ports/unix/manifest.py @@ -1,2 +1,2 @@ -freeze_as_mpy('$(MPY)/tools', 'upip.py') -freeze_as_mpy('$(MPY)/tools', 'upip_utarfile.py', opt=3) +freeze_as_mpy('$(MPY_DIR)/tools', 'upip.py') +freeze_as_mpy('$(MPY_DIR)/tools', 'upip_utarfile.py', opt=3) diff --git a/py/mkenv.mk b/py/mkenv.mk index 70d937c450c68..3efeb181648f0 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -66,6 +66,8 @@ MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py MPY_CROSS = $(TOP)/mpy-cross/mpy-cross MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py +MPY_LIB_DIR = $(TOP)/../micropython-lib + all: .PHONY: all diff --git a/py/mkrules.mk b/py/mkrules.mk index 2a7e1980c99c1..b43c6b8e37738 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -100,7 +100,7 @@ $(HEADER_BUILD): ifneq ($(FROZEN_MANIFEST),) # to build frozen_content.c from a manifest $(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h - $(Q)$(MAKE_MANIFEST) -o $@ $(TOP) $(BUILD) "$(MPY_CROSS_FLAGS)" $(FROZEN_MANIFEST) + $(Q)$(MAKE_MANIFEST) -o $@ -v "MPY_DIR=$(TOP)" -v "MPY_LIB_DIR=$(MPY_LIB_DIR)" -v "PORT_DIR=$(shell pwd)" -v "BOARD_DIR=$(BOARD_DIR)" -b "$(BUILD)" $(if $(MPY_CROSS_FLAGS),-f"$(MPY_CROSS_FLAGS)",) $(FROZEN_MANIFEST) endif ifneq ($(FROZEN_DIR),) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index 3017d7a21fea6..9889d50750273 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -38,14 +38,22 @@ def include(manifest): The manifest argument can be a string (filename) or an iterable of strings. + + Relative paths are resolved with respect to the current manifest file. """ if not isinstance(manifest, str): for m in manifest: include(m) else: + manifest = convert_path(manifest) with open(manifest) as f: + # Make paths relative to this manifest file while processing it. + # Applies to includes and input files. + prev_cwd = os.getcwd() + os.chdir(os.path.dirname(manifest)) exec(f.read()) + os.chdir(prev_cwd) def freeze(path, script=None, opt=0): """Freeze the input, automatically determining its type. A .py script @@ -57,6 +65,10 @@ def freeze(path, script=None, opt=0): the module will start after `path`, ie `path` is excluded from the module name. + If `path` is relative, it is resolved to the current manifest.py. + Use $(MPY_DIR), $(MPY_LIB_DIR), $(PORT_DIR), $(BOARD_DIR) if you need + to access specific paths. + If `script` is None all files in `path` will be frozen. If `script` is an iterable then freeze() is called on all items of the @@ -102,6 +114,8 @@ def freeze_mpy(path, script=None, opt=0): KIND_AS_MPY = 2 KIND_MPY = 3 +VARS = {} + manifest_list = [] class FreezeError(Exception): @@ -115,7 +129,12 @@ def system(cmd): return -1, er.output def convert_path(path): - return path.replace('$(MPY)', TOP) + # Perform variable substituion. + for name, value in VARS.items(): + path = path.replace('$({})'.format(name), value) + # Convert to absolute path (so that future operations don't rely on + # still being chdir'ed). + return os.path.abspath(path) def get_timestamp(path, default=None): try: @@ -173,23 +192,39 @@ def freeze_internal(kind, path, script, opt): manifest_list.append((kind, path, script, opt)) def main(): - global TOP - # Parse arguments - assert sys.argv[1] == '-o' - output_file = sys.argv[2] - TOP = sys.argv[3] - BUILD = sys.argv[4] - mpy_cross_flags = sys.argv[5] - input_manifest_list = sys.argv[6:] + import argparse + cmd_parser = argparse.ArgumentParser(description='A tool to generate frozen content in MicroPython firmware images.') + cmd_parser.add_argument('-o', '--output', help='output path') + cmd_parser.add_argument('-b', '--build-dir', help='output path') + cmd_parser.add_argument('-f', '--mpy-cross-flags', default='', help='flags to pass to mpy-cross') + cmd_parser.add_argument('-v', '--var', action='append', help='variables to substitute') + cmd_parser.add_argument('files', nargs='+', help='input manifest list') + args = cmd_parser.parse_args() + + # Extract variables for substitution. + for var in args.var: + name, value = var.split('=', 1) + if os.path.exists(value): + value = os.path.abspath(value) + VARS[name] = value + + if 'MPY_DIR' not in VARS or 'PORT_DIR' not in VARS: + print('MPY_DIR and PORT_DIR variables must be specified') + sys.exit(1) # Get paths to tools - MAKE_FROZEN = TOP + '/tools/make-frozen.py' - MPY_CROSS = TOP + '/mpy-cross/mpy-cross' - MPY_TOOL = TOP + '/tools/mpy-tool.py' + MAKE_FROZEN = VARS['MPY_DIR'] + '/tools/make-frozen.py' + MPY_CROSS = VARS['MPY_DIR'] + '/mpy-cross/mpy-cross' + MPY_TOOL = VARS['MPY_DIR'] + '/tools/mpy-tool.py' + + # Ensure mpy-cross is built + if not os.path.exists(MPY_CROSS): + print('mpy-cross not found at {}, please build it first'.format(MPY_CROSS)) + sys.exit(1) # Include top-level inputs, to generate the manifest - for input_manifest in input_manifest_list: + for input_manifest in args.files: try: if input_manifest.endswith('.py'): include(input_manifest) @@ -209,13 +244,13 @@ def main(): ts_outfile = get_timestamp_newest(path) elif kind == KIND_AS_MPY: infile = '{}/{}'.format(path, script) - outfile = '{}/frozen_mpy/{}.mpy'.format(BUILD, script[:-3]) + outfile = '{}/frozen_mpy/{}.mpy'.format(args.build_dir, script[:-3]) ts_infile = get_timestamp(infile) ts_outfile = get_timestamp(outfile, 0) if ts_infile >= ts_outfile: print('MPY', script) mkdir(outfile) - res, out = system([MPY_CROSS] + mpy_cross_flags.split() + ['-o', outfile, '-s', script, '-O{}'.format(opt), infile]) + res, out = system([MPY_CROSS] + args.mpy_cross_flags.split() + ['-o', outfile, '-s', script, '-O{}'.format(opt), infile]) if res != 0: print('error compiling {}: {}'.format(infile, out)) raise SystemExit(1) @@ -229,20 +264,26 @@ def main(): ts_newest = max(ts_newest, ts_outfile) # Check if output file needs generating - if ts_newest < get_timestamp(output_file, 0): + if ts_newest < get_timestamp(args.output, 0): # No files are newer than output file so it does not need updating return # Freeze paths as strings - _, output_str = system([MAKE_FROZEN] + str_paths) + res, output_str = system([MAKE_FROZEN] + str_paths) + if res != 0: + print('error freezing strings {}: {}'.format(str_paths, output_str)) + sys.exit(1) # Freeze .mpy files - _, output_mpy = system([MPY_TOOL, '-f', '-q', BUILD + '/genhdr/qstrdefs.preprocessed.h'] + mpy_files) + res, output_mpy = system([MPY_TOOL, '-f', '-q', args.build_dir + '/genhdr/qstrdefs.preprocessed.h'] + mpy_files) + if res != 0: + print('error freezing mpy {}: {}'.format(mpy_files, output_mpy)) + sys.exit(1) # Generate output - print('GEN', output_file) - mkdir(output_file) - with open(output_file, 'wb') as f: + print('GEN', args.output) + mkdir(args.output) + with open(args.output, 'wb') as f: f.write(b'//\n// Content for MICROPY_MODULE_FROZEN_STR\n//\n') f.write(output_str) f.write(b'//\n// Content for MICROPY_MODULE_FROZEN_MPY\n//\n') From 7662501d5b7c93fad6466b972d9912ee4fcc7660 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 19 Oct 2019 00:38:35 +1100 Subject: [PATCH 0602/1299] py/mkrules.mk: Add warning/error for invalid frozen config. --- py/mkrules.mk | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/py/mkrules.mk b/py/mkrules.mk index b43c6b8e37738..68da3e793cc86 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -101,15 +101,25 @@ ifneq ($(FROZEN_MANIFEST),) # to build frozen_content.c from a manifest $(BUILD)/frozen_content.c: FORCE $(BUILD)/genhdr/qstrdefs.generated.h $(Q)$(MAKE_MANIFEST) -o $@ -v "MPY_DIR=$(TOP)" -v "MPY_LIB_DIR=$(MPY_LIB_DIR)" -v "PORT_DIR=$(shell pwd)" -v "BOARD_DIR=$(BOARD_DIR)" -b "$(BUILD)" $(if $(MPY_CROSS_FLAGS),-f"$(MPY_CROSS_FLAGS)",) $(FROZEN_MANIFEST) + +ifneq ($(FROZEN_DIR),) +$(error FROZEN_DIR cannot be used in conjunction with FROZEN_MANIFEST) +endif + +ifneq ($(FROZEN_MPY_DIR),) +$(error FROZEN_MPY_DIR cannot be used in conjunction with FROZEN_MANIFEST) +endif endif ifneq ($(FROZEN_DIR),) +$(info Warning: FROZEN_DIR is deprecated in favour of FROZEN_MANIFEST) $(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DEPS) $(ECHO) "GEN $@" $(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@ endif ifneq ($(FROZEN_MPY_DIR),) +$(info Warning: FROZEN_MPY_DIR is deprecated in favour of FROZEN_MANIFEST) # make a list of all the .py files that need compiling and freezing FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)/==') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) From df7f632fd7003824500ec6c05f4395f667667d54 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 19 Oct 2019 00:39:04 +1100 Subject: [PATCH 0603/1299] esp8266: Allow building without a manifest. --- ports/esp8266/Makefile | 9 +++++++++ ports/esp8266/mpconfigport.h | 3 --- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index c4ffd4f811762..f1b718c781d95 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -189,6 +189,15 @@ $(BUILD)/uart.o: $(CONFVARS_FILE) FROZEN_EXTRA_DEPS = $(CONFVARS_FILE) +ifneq ($(FROZEN_MANIFEST)$(FROZEN_MPY_DIR),) +CFLAGS += -DMICROPY_MODULE_FROZEN_MPY +CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool +endif + +ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),) +CFLAGS += -DMICROPY_MODULE_FROZEN_STR +endif + .PHONY: deploy deploy: $(BUILD)/firmware-combined.bin diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index fa809d91a6513..e77f88c83c4d9 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -94,10 +94,7 @@ #define MICROPY_PY_STR_BYTES_CMP_WARN (1) #define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_STREAMS_POSIX_API (1) -#define MICROPY_MODULE_FROZEN_STR (1) -#define MICROPY_MODULE_FROZEN_MPY (1) #define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32 -#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_RPATH (2) From 93bd61ca91a3efcec9bc090fae193287bfa120e0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 19 Oct 2019 00:39:11 +1100 Subject: [PATCH 0604/1299] unix: Allow building without a manifest. --- ports/unix/Makefile | 5 ++++- ports/unix/mpconfigport.h | 1 - ports/unix/mpconfigport_fast.h | 5 ----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index b840856ffa9f5..bcc76ce160250 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -188,6 +188,9 @@ CFLAGS += -DMPZ_DIG_SIZE=16 # force 16 bits to work on both 32 and 64 bit archs MPY_CROSS_FLAGS += -mcache-lookup-bc endif +ifneq ($(FROZEN_MANIFEST)$(FROZEN_DIR),) +CFLAGS += -DMICROPY_MODULE_FROZEN_STR +endif include $(TOP)/py/mkrules.mk @@ -212,7 +215,7 @@ uninstall: # build synthetically fast interpreter for benchmarking fast: - $(MAKE) COPT="-O2 -DNDEBUG -fno-crossjumping" CFLAGS_EXTRA='-DMP_CONFIGFILE=""' BUILD=build-fast PROG=micropython_fast + $(MAKE) COPT="-O2 -DNDEBUG -fno-crossjumping" CFLAGS_EXTRA='-DMP_CONFIGFILE=""' BUILD=build-fast PROG=micropython_fast FROZEN_MANIFEST= # build a minimal interpreter minimal: diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 0ff6b2b06d927..1bb80f9704faf 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -113,7 +113,6 @@ #define MICROPY_PY_IO_IOBASE (1) #define MICROPY_PY_IO_FILEIO (1) #define MICROPY_PY_GC_COLLECT_RETVAL (1) -#define MICROPY_MODULE_FROZEN_STR (1) #ifndef MICROPY_STACKLESS #define MICROPY_STACKLESS (0) diff --git a/ports/unix/mpconfigport_fast.h b/ports/unix/mpconfigport_fast.h index 442159eb4f615..193567a2949fd 100644 --- a/ports/unix/mpconfigport_fast.h +++ b/ports/unix/mpconfigport_fast.h @@ -33,8 +33,3 @@ // 91 is a magic number proposed by @dpgeorge, which make pystone run ~ at tie // with CPython 3.4. #define MICROPY_MODULE_DICT_SIZE (91) - -// Don't include builtin upip, as this build is again intended just for -// synthetic benchmarking -#undef MICROPY_MODULE_FROZEN_STR -#define MICROPY_MODULE_FROZEN_STR (0) From ffd11486d426fa3b45946da72d274cd88be942d1 Mon Sep 17 00:00:00 2001 From: clach04 Date: Sun, 20 Oct 2019 18:22:20 -0700 Subject: [PATCH 0605/1299] tests/cpydiff: Fix typo in types_bytes_keywords.py doc comments. --- tests/cpydiff/types_bytes_keywords.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cpydiff/types_bytes_keywords.py b/tests/cpydiff/types_bytes_keywords.py index 4dc383f2627b7..bdba966f7fede 100644 --- a/tests/cpydiff/types_bytes_keywords.py +++ b/tests/cpydiff/types_bytes_keywords.py @@ -2,6 +2,6 @@ categories: Types,bytes description: bytes() with keywords not implemented cause: Unknown -workaround: Pass the encoding as a positional paramter, e.g. ``print(bytes('abc', 'utf-8'))`` +workaround: Pass the encoding as a positional parameter, e.g. ``print(bytes('abc', 'utf-8'))`` """ print(bytes('abc', encoding='utf8')) From 912892b2093f45a77986399f5e4600fe23b3efcf Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 21 Oct 2019 17:42:14 +1100 Subject: [PATCH 0606/1299] esp32: Add missing and necessary newline at EOF for sdkconfig.240mhz. When these files get concatenated the newline-at-EOF is necessary so that the start of the next file doesn't join with the end of the previous. --- ports/esp32/boards/sdkconfig.240mhz | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/boards/sdkconfig.240mhz b/ports/esp32/boards/sdkconfig.240mhz index a0cb113a48027..e36884009d1ed 100644 --- a/ports/esp32/boards/sdkconfig.240mhz +++ b/ports/esp32/boards/sdkconfig.240mhz @@ -2,4 +2,4 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y -CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 \ No newline at end of file +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 From f1d91908fa427cb419d6fcd5f64f6c581a0cdd0f Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 Oct 2019 00:23:22 +1100 Subject: [PATCH 0607/1299] esp8266/boards: Add manifest_release.py with files for a release. A release also sets: UART_OS = -1 --- ports/esp8266/boards/manifest_release.py | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 ports/esp8266/boards/manifest_release.py diff --git a/ports/esp8266/boards/manifest_release.py b/ports/esp8266/boards/manifest_release.py new file mode 100644 index 0000000000000..f2788c8157b74 --- /dev/null +++ b/ports/esp8266/boards/manifest_release.py @@ -0,0 +1,27 @@ +include('manifest.py') + +# drivers +freeze('$(MPY_DIR)/drivers/display', 'ssd1306.py') + +# file utilities +freeze('$(MPY_LIB_DIR)/upysh', 'upysh.py') + +# uasyncio +freeze('$(MPY_LIB_DIR)/uasyncio', 'uasyncio/__init__.py') +freeze('$(MPY_LIB_DIR)/uasyncio.core', 'uasyncio/core.py') + +# requests +freeze('$(MPY_LIB_DIR)/urequests', 'urequests.py') +freeze('$(MPY_LIB_DIR)/urllib.urequest', 'urllib/urequest.py') + +# umqtt with examples +freeze('$(MPY_LIB_DIR)/umqtt.simple', 'umqtt/simple.py') +freeze('$(MPY_LIB_DIR)/umqtt.robust', 'umqtt/robust.py') +freeze('$(MPY_LIB_DIR)/umqtt.simple', 'example_pub_button.py') +freeze('$(MPY_LIB_DIR)/umqtt.simple', 'example_sub_led.py') + +# HTTP examples +freeze('$(MPY_DIR)/examples/network', 'http_client.py') +freeze('$(MPY_DIR)/examples/network', 'http_client_ssl.py') +freeze('$(MPY_DIR)/examples/network', 'http_server.py') +freeze('$(MPY_DIR)/examples/network', 'http_server_ssl.py') From 56fc3edf989e1216b1a00d8ab75ebefff33a67e8 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 16 Oct 2019 20:45:44 +1100 Subject: [PATCH 0608/1299] extmod/modbluetooth: Make UUID support the buffer protocol. Internally change the representation of UUIDs to LE uint8* to simplify this. This allows UUIDs to be easily used in BLE payloads (such as advertising). Ref: #5186 --- extmod/modbluetooth.c | 88 +++++++++++++----------------------- extmod/modbluetooth.h | 16 ++++--- extmod/modbluetooth_nimble.c | 19 +++++--- 3 files changed, 53 insertions(+), 70 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 3c00d5c1b596b..1b98888448d83 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -122,10 +122,11 @@ STATIC mp_obj_t bluetooth_uuid_make_new(const mp_obj_type_t *type, size_t n_args if (value > 65535) { mp_raise_ValueError("invalid UUID"); } - self->uuid._16 = value; + self->data[0] = value & 0xff; + self->data[1] = (value >> 8) & 0xff; } else { self->type = MP_BLUETOOTH_UUID_TYPE_128; - mp_bluetooth_parse_uuid_128bit_str(all_args[0], self->uuid._128); + mp_bluetooth_parse_uuid_128bit_str(all_args[0], self->data); } return self; @@ -135,41 +136,39 @@ STATIC mp_obj_t bluetooth_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_HASH: { - if (self->type == MP_BLUETOOTH_UUID_TYPE_16) { - return mp_unary_op(MP_UNARY_OP_HASH, MP_OBJ_NEW_SMALL_INT(self->uuid._16)); - - } else if (self->type == MP_BLUETOOTH_UUID_TYPE_32) { - return mp_unary_op(MP_UNARY_OP_HASH, MP_OBJ_NEW_SMALL_INT(self->uuid._32)); - - } else if (self->type == MP_BLUETOOTH_UUID_TYPE_128) { - return MP_OBJ_NEW_SMALL_INT(qstr_compute_hash(self->uuid._128, sizeof(self->uuid._128))); - } - return MP_OBJ_NULL; + // Use the QSTR hash function. + return MP_OBJ_NEW_SMALL_INT(qstr_compute_hash(self->data, self->type)); } default: return MP_OBJ_NULL; // op not supported } } - STATIC void bluetooth_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->type == MP_BLUETOOTH_UUID_TYPE_16) { - mp_printf(print, "UUID16(0x%04x)", self->uuid._16); - } else if (self->type == MP_BLUETOOTH_UUID_TYPE_32) { - mp_printf(print, "UUID32(0x%08x)", self->uuid._32); - } else if (self->type == MP_BLUETOOTH_UUID_TYPE_128) { - mp_printf(print, "UUID128('"); - for (int i = 0; i < 16; ++i) { - mp_printf(print, "%02x", self->uuid._128[15-i]); - if (i == 3 || i == 5 || i == 7 || i == 9) { - mp_printf(print, "-"); - } + mp_printf(print, "UUID%u(%s", self->type * 8, self->type <= 4 ? "0x" : "'"); + for (int i = 0; i < self->type; ++i) { + if (i == 4 || i == 6 || i == 8 || i == 10) { + mp_printf(print, "-"); } - mp_printf(print, "')"); - } else { - mp_printf(print, "UUID?(%d)", self->type); + mp_printf(print, "%02x", self->data[self->type - 1 - i]); + } + if (self->type == MP_BLUETOOTH_UUID_TYPE_128) { + mp_printf(print, "'"); + } + mp_printf(print, ")"); +} + +mp_int_t bluetooth_uuid_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); + + if (flags != MP_BUFFER_READ) { + return 1; } + + bufinfo->buf = self->data; + bufinfo->len = self->type; + bufinfo->typecode = 'B'; + return 0; } #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE @@ -177,19 +176,8 @@ STATIC void bluetooth_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_p STATIC void ringbuf_put_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) { assert(ringbuf_free(ringbuf) >= uuid->type + 1); ringbuf_put(ringbuf, uuid->type); - switch (uuid->type) { - case MP_BLUETOOTH_UUID_TYPE_16: - ringbuf_put16(ringbuf, uuid->uuid._16); - break; - case MP_BLUETOOTH_UUID_TYPE_32: - ringbuf_put16(ringbuf, uuid->uuid._32 >> 16); - ringbuf_put16(ringbuf, uuid->uuid._32 & 0xffff); - break; - case MP_BLUETOOTH_UUID_TYPE_128: - for (int i = 0; i < 16; ++i) { - ringbuf_put(ringbuf, uuid->uuid._128[i]); - } - break; + for (int i = 0; i < uuid->type; ++i) { + ringbuf_put(ringbuf, uuid->data[i]); } } @@ -197,21 +185,8 @@ STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid) assert(ringbuf_avail(ringbuf) >= 1); uuid->type = ringbuf_get(ringbuf); assert(ringbuf_avail(ringbuf) >= uuid->type); - uint16_t h, l; - switch (uuid->type) { - case MP_BLUETOOTH_UUID_TYPE_16: - uuid->uuid._16 = ringbuf_get16(ringbuf); - break; - case MP_BLUETOOTH_UUID_TYPE_32: - h = ringbuf_get16(ringbuf); - l = ringbuf_get16(ringbuf); - uuid->uuid._32 = (h << 16) | l; - break; - case MP_BLUETOOTH_UUID_TYPE_128: - for (int i = 0; i < 16; ++i) { - uuid->uuid._128[i] = ringbuf_get(ringbuf); - } - break; + for (int i = 0; i < uuid->type; ++i) { + uuid->data[i] = ringbuf_get(ringbuf); } } #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE @@ -223,6 +198,7 @@ STATIC const mp_obj_type_t bluetooth_uuid_type = { .unary_op = bluetooth_uuid_unary_op, .locals_dict = NULL, .print = bluetooth_uuid_print, + .buffer_p = { .get_buffer = bluetooth_uuid_get_buffer }, }; // ---------------------------------------------------------------------------- diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index f7284a43e8b21..e99641e8f7457 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -120,14 +120,14 @@ _IRQ_ALL = const(0xffff) // Common UUID type. // Ports are expected to map this to their own internal UUID types. +// Internally the UUID data is little-endian, but the user should only +// ever see this if they use the buffer protocol, e.g. in order to +// construct an advertising payload (which needs to be in LE). +// Both the constructor and the print function work in BE. typedef struct { mp_obj_base_t base; uint8_t type; - union { - uint16_t _16; - uint32_t _32; - uint8_t _128[16]; - } uuid; + uint8_t data[16]; } mp_obj_bluetooth_uuid_t; ////////////////////////////////////////////////////////////// @@ -140,8 +140,10 @@ typedef struct { // Any method returning an int returns errno on failure, otherwise zero. // Note: All methods dealing with addresses (as 6-byte uint8 pointers) are in big-endian format. -// (i.e. the same way they would be printed on a device sticker or in a UI). -// This means that the lower level implementation might need to reorder them (e.g. Nimble works in little-endian) +// (i.e. the same way they would be printed on a device sticker or in a UI), so the user sees +// addresses in a way that looks like what they'd expect. +// This means that the lower level implementation will likely need to reorder them (e.g. Nimble +// works in little-endian, as does BLE itself). // Enables the Bluetooth stack. int mp_bluetooth_init(void); diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 131b73574dddf..c09f1cd2de94a 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -87,21 +87,22 @@ STATIC int ble_hs_err_to_errno(int err) { } } +// Note: modbluetooth UUIDs store their data in LE. STATIC ble_uuid_t* create_nimble_uuid(const mp_obj_bluetooth_uuid_t *uuid) { if (uuid->type == MP_BLUETOOTH_UUID_TYPE_16) { ble_uuid16_t *result = m_new(ble_uuid16_t, 1); result->u.type = BLE_UUID_TYPE_16; - result->value = uuid->uuid._16; + result->value = (uuid->data[1] << 8) | uuid->data[0]; return (ble_uuid_t*)result; } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_32) { ble_uuid32_t *result = m_new(ble_uuid32_t, 1); result->u.type = BLE_UUID_TYPE_32; - result->value = uuid->uuid._32; + result->value = (uuid->data[1] << 24) | (uuid->data[1] << 16) | (uuid->data[1] << 8) | uuid->data[0]; return (ble_uuid_t*)result; } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_128) { ble_uuid128_t *result = m_new(ble_uuid128_t, 1); result->u.type = BLE_UUID_TYPE_128; - memcpy(result->value, uuid->uuid._128, 16); + memcpy(result->value, uuid->data, 16); return (ble_uuid_t*)result; } else { return NULL; @@ -115,15 +116,19 @@ STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(const ble_uuid_any_t *uuid) { switch (uuid->u.type) { case BLE_UUID_TYPE_16: result.type = MP_BLUETOOTH_UUID_TYPE_16; - result.uuid._16 = uuid->u16.value; + result.data[0] = uuid->u16.value & 0xff; + result.data[1] = (uuid->u16.value << 8) & 0xff; break; case BLE_UUID_TYPE_32: result.type = MP_BLUETOOTH_UUID_TYPE_32; - result.uuid._32 = uuid->u32.value; + result.data[0] = uuid->u32.value & 0xff; + result.data[1] = (uuid->u32.value << 8) & 0xff; + result.data[2] = (uuid->u32.value << 16) & 0xff; + result.data[3] = (uuid->u32.value << 24) & 0xff; break; case BLE_UUID_TYPE_128: result.type = MP_BLUETOOTH_UUID_TYPE_128; - memcpy(result.uuid._128, uuid->u128.value, 16); + memcpy(result.data, uuid->u128.value, 16); break; default: assert(false); @@ -131,7 +136,7 @@ STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(const ble_uuid_any_t *uuid) { return result; } -// modbluetooth (and the layers above it) work in BE addresses, Nimble works in LE. +// modbluetooth (and the layers above it) work in BE for addresses, Nimble works in LE. STATIC void reverse_addr_byte_order(uint8_t *addr_out, const uint8_t *addr_in) { for (int i = 0; i < 6; ++i) { addr_out[i] = addr_in[5-i]; From 3e1af5b36fc181231b6c7b7603b21490fb9b22e6 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 22 Oct 2019 12:31:40 +1100 Subject: [PATCH 0609/1299] examples/bluetooth: Use UUIDs directly to add services to adv payload. --- examples/bluetooth/ble_advertising.py | 15 +++++++++++++-- examples/bluetooth/ble_temperature.py | 2 +- examples/bluetooth/ble_uart_peripheral.py | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/examples/bluetooth/ble_advertising.py b/examples/bluetooth/ble_advertising.py index f52598a62a54f..b57d5e031c2f1 100644 --- a/examples/bluetooth/ble_advertising.py +++ b/examples/bluetooth/ble_advertising.py @@ -11,8 +11,14 @@ _ADV_TYPE_FLAGS = const(0x01) _ADV_TYPE_NAME = const(0x09) _ADV_TYPE_UUID16_COMPLETE = const(0x3) +_ADV_TYPE_UUID32_COMPLETE = const(0x5) +_ADV_TYPE_UUID128_COMPLETE = const(0x7) +_ADV_TYPE_UUID16_MORE = const(0x2) +_ADV_TYPE_UUID32_MORE = const(0x4) +_ADV_TYPE_UUID128_MORE = const(0x6) _ADV_TYPE_APPEARANCE = const(0x19) + # Generate a payload to be passed to gap_advertise(adv_data=...). def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): payload = bytearray() @@ -28,8 +34,13 @@ def _append(adv_type, value): if services: for uuid in services: - # TODO: Support bluetooth.UUID class. - _append(_ADV_TYPE_UUID16_COMPLETE, struct.pack(' Date: Tue, 22 Oct 2019 12:36:02 +1100 Subject: [PATCH 0610/1299] py/objstr: Size-optimise failure path for mp_obj_str_get_buffer. These fields are never looked at if the function returns non-zero. --- py/objstr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/py/objstr.c b/py/objstr.c index 8824363637c49..e221982c576e0 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1913,9 +1913,6 @@ mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_u return 0; } else { // can't write to a string - bufinfo->buf = NULL; - bufinfo->len = 0; - bufinfo->typecode = -1; return 1; } } From f34e16dbc6648a46590501bbc5e4b146bd032eef Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 21 Oct 2019 22:35:58 +1100 Subject: [PATCH 0611/1299] extmod/modbluetooth: Persist reference to NimBLE service instances. NimBLE doesn't actually copy this data, it requires it to stay live. Only dereference when we register a new set of services. Fixes #5226 This will allow incrementally adding services in the future, so rename `reset` to `append` to make it clearer. --- extmod/modbluetooth.c | 6 +++--- extmod/modbluetooth.h | 2 +- extmod/modbluetooth_nimble.c | 15 ++++++++------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 1b98888448d83..2a3e87bc2489c 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -421,9 +421,9 @@ STATIC mp_obj_t bluetooth_ble_gatts_register_services(mp_obj_t self_in, mp_obj_t uint16_t **handles = m_new0(uint16_t*, len); size_t *num_handles = m_new0(size_t, len); - // We always reset the service list, as Nimble has no other option. - // TODO: Add a `reset` or `clear` kwarg (defaulting to True) to make this behavior optional. - int err = mp_bluetooth_gatts_register_service_begin(true); + // TODO: Add a `append` kwarg (defaulting to False) to make this behavior optional. + bool append = false; + int err = mp_bluetooth_gatts_register_service_begin(append); if (err != 0) { return bluetooth_handle_errno(err); } diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index e99641e8f7457..20476b183c233 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -165,7 +165,7 @@ int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, cons void mp_bluetooth_gap_advertise_stop(void); // Start adding services. Must be called before mp_bluetooth_register_service. -int mp_bluetooth_gatts_register_service_begin(bool reset); +int mp_bluetooth_gatts_register_service_begin(bool append); // // Add a service with the given list of characteristics to the queue to be registered. // The value_handles won't be valid until after mp_bluetooth_register_service_end is called. int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics); diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index c09f1cd2de94a..d873368581875 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -440,7 +440,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, return BLE_ATT_ERR_UNLIKELY; } -int mp_bluetooth_gatts_register_service_begin(bool reset) { +int mp_bluetooth_gatts_register_service_begin(bool append) { int ret = ble_gatts_reset(); if (ret != 0) { return ble_hs_err_to_errno(ret); @@ -452,7 +452,13 @@ int mp_bluetooth_gatts_register_service_begin(bool reset) { // By default, just register the default gap service. ble_svc_gap_init(); - MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services = 0; + if (!append) { + // Unref any previous service definitions. + for (int i = 0; i < MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services; ++i) { + MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[i] = NULL; + } + MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services = 0; + } return 0; } @@ -463,11 +469,6 @@ int mp_bluetooth_gatts_register_service_end() { return ble_hs_err_to_errno(ret); } - for (int i = 0; i < MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services; ++i) { - MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[i] = NULL; - } - MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services = 0; - return 0; } From 2c1f269918331a50678119410219e965fcdb822e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 22 Oct 2019 01:03:17 +1100 Subject: [PATCH 0612/1299] extmod/modbluetooth_nimble: Use `data_alloc` length to truncate writes. This allows the maximum size of a characteristic/descriptor to be increased by locally writing to it first. --- extmod/modbluetooth_nimble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index d873368581875..6287ca89ee8fb 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -430,7 +430,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, return BLE_ATT_ERR_ATTR_NOT_FOUND; } entry = MP_OBJ_TO_PTR(elem->value); - entry->data_len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(ctxt->om)); + entry->data_len = MIN(entry->data_alloc, OS_MBUF_PKTLEN(ctxt->om)); os_mbuf_copydata(ctxt->om, 0, entry->data_len, entry->data); mp_bluetooth_gatts_on_write(conn_handle, value_handle); From 9c5262f25ef29950da241380c76e035b3a8cec38 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 22 Oct 2019 01:04:48 +1100 Subject: [PATCH 0613/1299] examples/bluetooth/ble_uart_peripheral.py: Add usage demo. --- examples/bluetooth/ble_uart_peripheral.py | 28 +++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/examples/bluetooth/ble_uart_peripheral.py b/examples/bluetooth/ble_uart_peripheral.py index 3508a15e7b241..90cdbcaf526dd 100644 --- a/examples/bluetooth/ble_uart_peripheral.py +++ b/examples/bluetooth/ble_uart_peripheral.py @@ -75,5 +75,29 @@ def _advertise(self, interval_us=500000): self._ble.gap_advertise(interval_us, adv_data=self._payload) -# ble = bluetooth.BLE() -# uart = BLEUART(ble) +def demo(): + import time + + ble = bluetooth.BLE() + uart = BLEUART(ble) + + def on_rx(): + print('rx: ', uart.read().decode().strip()) + + uart.irq(handler=on_rx) + nums = [4, 8, 15, 16, 23, 42] + i = 0 + + try: + while True: + uart.write(str(nums[i]) + '\n') + i = (i + 1) % len(nums) + time.sleep_ms(1000) + except KeyboardInterrupt: + pass + + uart.close() + + +if __name__ == '__main__': + demo() From d2384efa809953152c57cbda4c339dfbaa64cf29 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 Oct 2019 01:06:34 +1100 Subject: [PATCH 0614/1299] py: Automatically provide weak links from "foo" to "ufoo" module name. This commit implements automatic module weak links for all built-in modules, by searching for "ufoo" in the built-in module list if "foo" cannot be found. This means that all modules named "ufoo" are always available as "foo". Also, a port can no longer add any other weak links, which makes strict the definition of a weak link. It saves some code size (about 100-200 bytes) on ports that previously had lots of weak links. Some changes from the previous behaviour: - It doesn't intern the non-u module names (eg "foo" is not interned), which saves code size, but will mean that "import foo" creates a new qstr (namely "foo") in RAM (unless the importing module is frozen). - help('modules') no longer lists non-u module names, only the u-variants; this reduces duplication in the help listing. Weak links are effectively the same as having a set of symbolic links on the filesystem that is searched last. So an "import foo" will search built-in modules first, then all paths in sys.path, then weak links last, importing "ufoo" if it exists. Thus a file called "foo.py" somewhere in sys.path will still have precedence over the weak link of "foo" to "ufoo". See issues: #1740, #4449, #5229, #5241. --- ports/cc3200/mpconfigport.h | 13 ------------- ports/esp32/mpconfigport.h | 18 ------------------ ports/esp8266/mpconfigport.h | 17 ----------------- ports/javascript/mpconfigport.h | 15 --------------- ports/nrf/mpconfigport.h | 4 ---- ports/stm32/mpconfigport.h | 28 ---------------------------- ports/zephyr/mpconfigport.h | 6 ------ py/builtinhelp.c | 4 ---- py/builtinimport.c | 27 ++++++++++++--------------- py/mpconfig.h | 5 ----- py/objmodule.c | 26 +++++++++++++++++--------- py/objmodule.h | 4 +++- 12 files changed, 32 insertions(+), 135 deletions(-) diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h index e7894dd023c84..d5c3c07e43602 100644 --- a/ports/cc3200/mpconfigport.h +++ b/ports/cc3200/mpconfigport.h @@ -169,19 +169,6 @@ extern const struct _mp_obj_module_t mp_module_ussl; { MP_ROM_QSTR(MP_QSTR_ubinascii), MP_ROM_PTR(&mp_module_ubinascii) }, \ { MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) }, \ -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, \ - { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_ustruct) }, \ - { MP_ROM_QSTR(MP_QSTR_re), MP_ROM_PTR(&mp_module_ure) }, \ - { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_ujson) }, \ - { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&mp_module_uos) }, \ - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ - { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_module_uselect) }, \ - { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) }, \ - { MP_ROM_QSTR(MP_QSTR_binascii), MP_ROM_PTR(&mp_module_ubinascii) }, \ - { MP_ROM_QSTR(MP_QSTR_ssl), MP_ROM_PTR(&mp_module_ussl) }, \ - { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \ - // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 5c9d602abcc27..89e5373472b3a 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -212,24 +212,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_collections), (mp_obj_t)&mp_module_collections }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_hashlib), (mp_obj_t)&mp_module_uhashlib }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_heapq), (mp_obj_t)&mp_module_uheapq }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_io), (mp_obj_t)&mp_module_io }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&mp_module_urandom }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_module_uselect }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_ssl), (mp_obj_t)&mp_module_ussl }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_zlib), (mp_obj_t)&mp_module_uzlib }, \ - #define MP_STATE_PORT MP_STATE_VM struct _machine_timer_obj_t; diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index e77f88c83c4d9..7263193928ffe 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -167,23 +167,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \ { MP_ROM_QSTR(MP_QSTR__onewire), MP_ROM_PTR(&mp_module_onewire) }, \ -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_ROM_QSTR(MP_QSTR_binascii), MP_ROM_PTR(&mp_module_ubinascii) }, \ - { MP_ROM_QSTR(MP_QSTR_collections), MP_ROM_PTR(&mp_module_collections) }, \ - { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, \ - { MP_ROM_QSTR(MP_QSTR_hashlib), MP_ROM_PTR(&mp_module_uhashlib) }, \ - { MP_ROM_QSTR(MP_QSTR_io), MP_ROM_PTR(&mp_module_io) }, \ - { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_ujson) }, \ - { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&uos_module) }, \ - { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mp_module_urandom) }, \ - { MP_ROM_QSTR(MP_QSTR_re), MP_ROM_PTR(&mp_module_ure) }, \ - { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_module_uselect) }, \ - { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_lwip) }, \ - { MP_ROM_QSTR(MP_QSTR_ssl), MP_ROM_PTR(&mp_module_ussl) }, \ - { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_ustruct) }, \ - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&utime_module) }, \ - { MP_ROM_QSTR(MP_QSTR_zlib), MP_ROM_PTR(&mp_module_uzlib) }, \ - #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ diff --git a/ports/javascript/mpconfigport.h b/ports/javascript/mpconfigport.h index 02d83f402d291..8ea43d84ce38a 100644 --- a/ports/javascript/mpconfigport.h +++ b/ports/javascript/mpconfigport.h @@ -131,21 +131,6 @@ extern const struct _mp_obj_module_t mp_module_utime; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_ROM_QSTR(MP_QSTR_binascii), MP_ROM_PTR(&mp_module_ubinascii) }, \ - { MP_ROM_QSTR(MP_QSTR_collections), MP_ROM_PTR(&mp_module_collections) }, \ - { MP_ROM_QSTR(MP_QSTR_re), MP_ROM_PTR(&mp_module_ure) }, \ - { MP_ROM_QSTR(MP_QSTR_zlib), MP_ROM_PTR(&mp_module_uzlib) }, \ - { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_ujson) }, \ - { MP_ROM_QSTR(MP_QSTR_heapq), MP_ROM_PTR(&mp_module_uheapq) }, \ - { MP_ROM_QSTR(MP_QSTR_hashlib), MP_ROM_PTR(&mp_module_uhashlib) }, \ - { MP_ROM_QSTR(MP_QSTR_io), MP_ROM_PTR(&mp_module_io) }, \ - { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mp_module_urandom) }, \ - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ - { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_module_uselect) }, \ - { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_ustruct) }, \ - { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, \ - //#define MICROPY_EVENT_POLL_HOOK {ets_event_poll();} #if MICROPY_PY_THREAD #define MICROPY_EVENT_POLL_HOOK \ diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index da9a03e1d03b5..71f9f6804d1b0 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -281,10 +281,6 @@ extern const struct _mp_obj_module_t ble_module; #endif // BLUETOOTH_SD -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&mp_module_uos) }, \ - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ - // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ { MP_ROM_QSTR(MP_QSTR_help), MP_ROM_PTR(&mp_builtin_help_obj) }, \ diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 5806755116f95..2cc37e3bf2bf4 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -223,21 +223,12 @@ extern const struct _mp_obj_module_t mp_module_onewire; #if MICROPY_PY_USOCKET && MICROPY_PY_LWIP // usocket implementation provided by lwIP #define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_lwip) }, -#define SOCKET_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_lwip) }, #elif MICROPY_PY_USOCKET // usocket implementation provided by skeleton wrapper #define SOCKET_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, -#define SOCKET_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) }, #else // no usocket module #define SOCKET_BUILTIN_MODULE -#define SOCKET_BUILTIN_MODULE_WEAK_LINKS -#endif - -#if MICROPY_PY_USSL -#define SSL_BUILTIN_MODULE_WEAK_LINKS { MP_ROM_QSTR(MP_QSTR_ssl), MP_ROM_PTR(&mp_module_ussl) }, -#else -#define SSL_BUILTIN_MODULE_WEAK_LINKS #endif #if MICROPY_PY_NETWORK @@ -263,25 +254,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; BLUETOOTH_BUILTIN_MODULE \ { MP_ROM_QSTR(MP_QSTR__onewire), MP_ROM_PTR(&mp_module_onewire) }, \ -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_ROM_QSTR(MP_QSTR_binascii), MP_ROM_PTR(&mp_module_ubinascii) }, \ - { MP_ROM_QSTR(MP_QSTR_collections), MP_ROM_PTR(&mp_module_collections) }, \ - { MP_ROM_QSTR(MP_QSTR_re), MP_ROM_PTR(&mp_module_ure) }, \ - { MP_ROM_QSTR(MP_QSTR_zlib), MP_ROM_PTR(&mp_module_uzlib) }, \ - { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_ujson) }, \ - { MP_ROM_QSTR(MP_QSTR_heapq), MP_ROM_PTR(&mp_module_uheapq) }, \ - { MP_ROM_QSTR(MP_QSTR_hashlib), MP_ROM_PTR(&mp_module_uhashlib) }, \ - { MP_ROM_QSTR(MP_QSTR_io), MP_ROM_PTR(&mp_module_io) }, \ - { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&mp_module_uos) }, \ - { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mp_module_urandom) }, \ - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_utime) }, \ - { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_module_uselect) }, \ - SOCKET_BUILTIN_MODULE_WEAK_LINKS \ - SSL_BUILTIN_MODULE_WEAK_LINKS \ - { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&mp_module_ustruct) }, \ - { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&machine_module) }, \ - { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, \ - // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ diff --git a/ports/zephyr/mpconfigport.h b/ports/zephyr/mpconfigport.h index 0b35de35b7840..1ca357756c9dc 100644 --- a/ports/zephyr/mpconfigport.h +++ b/ports/zephyr/mpconfigport.h @@ -119,10 +119,8 @@ extern const struct _mp_obj_module_t mp_module_zsensor; #if MICROPY_PY_USOCKET #define MICROPY_PY_USOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) }, -#define MICROPY_PY_USOCKET_WEAK_DEF { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) }, #else #define MICROPY_PY_USOCKET_DEF -#define MICROPY_PY_USOCKET_WEAK_DEF #endif #if MICROPY_PY_UTIME @@ -150,10 +148,6 @@ extern const struct _mp_obj_module_t mp_module_zsensor; MICROPY_PY_ZEPHYR_DEF \ MICROPY_PY_ZSENSOR_DEF \ -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_time) }, \ - MICROPY_PY_USOCKET_WEAK_DEF \ - // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ diff --git a/py/builtinhelp.c b/py/builtinhelp.c index a7fede00acea0..8f162d8858314 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -80,10 +80,6 @@ STATIC void mp_help_print_modules(void) { mp_help_add_from_map(list, &mp_builtin_module_map); - #if MICROPY_MODULE_WEAK_LINKS - mp_help_add_from_map(list, &mp_builtin_module_weak_links_map); - #endif - #if MICROPY_MODULE_FROZEN_STR extern const char mp_frozen_str_names[]; mp_help_add_from_names(list, mp_frozen_str_names); diff --git a/py/builtinimport.c b/py/builtinimport.c index 008a21dcff5e2..b9f6c2ab2dd23 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -381,21 +381,18 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { DEBUG_printf("Current path: %.*s\n", vstr_len(&path), vstr_str(&path)); if (stat == MP_IMPORT_STAT_NO_EXIST) { + module_obj = MP_OBJ_NULL; #if MICROPY_MODULE_WEAK_LINKS // check if there is a weak link to this module if (i == mod_len) { - mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP); - if (el == NULL) { - goto no_exist; + module_obj = mp_module_search_umodule(mod_str); + if (module_obj != MP_OBJ_NULL) { + // found weak linked module + mp_module_call_init(mod_name, module_obj); } - // found weak linked module - module_obj = el->value; - mp_module_call_init(mod_name, module_obj); - } else { - no_exist: - #else - { + } #endif + if (module_obj == MP_OBJ_NULL) { // couldn't find the file, so fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_ImportError, "module not found"); @@ -492,11 +489,11 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #if MICROPY_MODULE_WEAK_LINKS // Check if there is a weak link to this module - mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(module_name_qstr), MP_MAP_LOOKUP); - if (el != NULL) { + module_obj = mp_module_search_umodule(qstr_str(module_name_qstr)); + if (module_obj != MP_OBJ_NULL) { // Found weak-linked module - mp_module_call_init(module_name_qstr, el->value); - return el->value; + mp_module_call_init(module_name_qstr, module_obj); + return module_obj; } #endif diff --git a/py/mpconfig.h b/py/mpconfig.h index 4172b5fcfeb6c..e46da3e83c721 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1392,11 +1392,6 @@ typedef double mp_float_t; #define MICROPY_PORT_BUILTIN_MODULES #endif -// Any module weak links - see objmodule.c:mp_builtin_module_weak_links_table. -#ifndef MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS -#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS -#endif - // Additional constant definitions for the compiler - see compile.c:mp_constants_table. #ifndef MICROPY_PORT_CONSTANTS #define MICROPY_PORT_CONSTANTS diff --git a/py/objmodule.c b/py/objmodule.c index 4a07913c5e2e2..d725bb6a14537 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2014-2015 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -26,6 +26,7 @@ */ #include +#include #include #include "py/objmodule.h" @@ -235,14 +236,6 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = { MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table); -#if MICROPY_MODULE_WEAK_LINKS -STATIC const mp_rom_map_elem_t mp_builtin_module_weak_links_table[] = { - MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS -}; - -MP_DEFINE_CONST_MAP(mp_builtin_module_weak_links_map, mp_builtin_module_weak_links_table); -#endif - // returns MP_OBJ_NULL if not found mp_obj_t mp_module_get(qstr module_name) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; @@ -267,6 +260,21 @@ void mp_module_register(qstr qst, mp_obj_t module) { mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module; } +#if MICROPY_MODULE_WEAK_LINKS +// Search for u"foo" in built-in modules, return MP_OBJ_NULL if not found +mp_obj_t mp_module_search_umodule(const char *module_str) { + for (size_t i = 0; i < MP_ARRAY_SIZE(mp_builtin_module_table); ++i) { + const mp_map_elem_t *entry = (const mp_map_elem_t*)&mp_builtin_module_table[i]; + const char *key = qstr_str(MP_OBJ_QSTR_VALUE(entry->key)); + if (key[0] == 'u' && strcmp(&key[1], module_str) == 0) { + return (mp_obj_t)entry->value; + } + + } + return MP_OBJ_NULL; +} +#endif + #if MICROPY_MODULE_BUILTIN_INIT void mp_module_call_init(qstr module_name, mp_obj_t module_obj) { // Look for __init__ and call it if it exists diff --git a/py/objmodule.h b/py/objmodule.h index b7702ec50b686..33a0ff07e1ece 100644 --- a/py/objmodule.h +++ b/py/objmodule.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2019 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,8 @@ extern const mp_map_t mp_builtin_module_weak_links_map; mp_obj_t mp_module_get(qstr module_name); void mp_module_register(qstr qstr, mp_obj_t module); +mp_obj_t mp_module_search_umodule(const char *module_str); + #if MICROPY_MODULE_BUILTIN_INIT void mp_module_call_init(qstr module_name, mp_obj_t module_obj); #else From 1582c7eeb0707acc5d645c0a5a9e59d14ff7c8be Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 Oct 2019 01:08:27 +1100 Subject: [PATCH 0615/1299] unix,windows: Enable module weak links. --- ports/unix/mpconfigport.h | 1 + ports/windows/mpconfigport.h | 1 + 2 files changed, 2 insertions(+) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 1bb80f9704faf..e42ad5e49c147 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -70,6 +70,7 @@ #ifndef MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) #endif +#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_DESCRIPTORS (1) diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h index 1a9842609ada6..fae01d74ee3ca 100644 --- a/ports/windows/mpconfigport.h +++ b/ports/windows/mpconfigport.h @@ -60,6 +60,7 @@ #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_OPT_COMPUTED_GOTO (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) +#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_DESCRIPTORS (1) From 21a60935a5d5885817881b4f690fdfd3ef009100 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 Oct 2019 16:35:46 +1100 Subject: [PATCH 0616/1299] py/modarray: Rename "array" module to "uarray". Following the other modules like ustruct, ucollections. See issues #4370 and #4449. --- py/builtin.h | 2 +- py/modarray.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/py/builtin.h b/py/builtin.h index a5e0f5f2d0fbb..1928577be864e 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -89,7 +89,7 @@ MP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj); extern const mp_obj_module_t mp_module___main__; extern const mp_obj_module_t mp_module_builtins; -extern const mp_obj_module_t mp_module_array; +extern const mp_obj_module_t mp_module_uarray; extern const mp_obj_module_t mp_module_collections; extern const mp_obj_module_t mp_module_io; extern const mp_obj_module_t mp_module_math; diff --git a/py/modarray.c b/py/modarray.c index de84fc85871af..b459a837569dc 100644 --- a/py/modarray.c +++ b/py/modarray.c @@ -29,17 +29,17 @@ #if MICROPY_PY_ARRAY STATIC const mp_rom_map_elem_t mp_module_array_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_array) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uarray) }, { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_type_array) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_array_globals, mp_module_array_globals_table); -const mp_obj_module_t mp_module_array = { +const mp_obj_module_t mp_module_uarray = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_array_globals, }; -MP_REGISTER_MODULE(MP_QSTR_array, mp_module_array, MICROPY_PY_ARRAY); +MP_REGISTER_MODULE(MP_QSTR_uarray, mp_module_uarray, MICROPY_PY_ARRAY); #endif From a2eea57b1d5456696598703aa4ffdbc7e9fb52ea Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 Oct 2019 16:40:58 +1100 Subject: [PATCH 0617/1299] docs/library: Rename "array" module to "uarray". --- docs/library/index.rst | 2 +- docs/library/{array.rst => uarray.rst} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename docs/library/{array.rst => uarray.rst} (82%) diff --git a/docs/library/index.rst b/docs/library/index.rst index dc89766e2d188..223304881a758 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -74,12 +74,12 @@ it will fallback to loading the built-in ``ujson`` module. :maxdepth: 1 builtins.rst - array.rst bluetooth.rst cmath.rst gc.rst math.rst sys.rst + uarray.rst ubinascii.rst ucollections.rst uerrno.rst diff --git a/docs/library/array.rst b/docs/library/uarray.rst similarity index 82% rename from docs/library/array.rst rename to docs/library/uarray.rst index f837b034369b6..9fa82ff31b5c9 100644 --- a/docs/library/array.rst +++ b/docs/library/uarray.rst @@ -1,7 +1,7 @@ -:mod:`array` -- arrays of numeric data -====================================== +:mod:`uarray` -- arrays of numeric data +======================================= -.. module:: array +.. module:: uarray :synopsis: efficient arrays of numeric data |see_cpython_module| :mod:`python:array`. @@ -13,7 +13,7 @@ floating-point support). Classes ------- -.. class:: array.array(typecode, [iterable]) +.. class:: array(typecode, [iterable]) Create array with elements of given type. Initial contents of the array are given by *iterable*. If it is not provided, an empty From 30e25174bbf077e8a3cbe2a3a6a97795f8d67dc2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 22 Oct 2019 17:33:23 +1100 Subject: [PATCH 0618/1299] tests: Rename "array" module to "uarray". --- tests/basics/array1.py | 9 ++++++--- tests/basics/array_add.py | 9 ++++++--- tests/basics/array_construct.py | 9 ++++++--- tests/basics/array_construct2.py | 9 ++++++--- tests/basics/array_construct_endian.py | 9 ++++++--- tests/basics/array_intbig.py | 9 ++++++--- tests/basics/array_micropython.py | 9 ++++++--- tests/basics/bytearray_construct_array.py | 9 ++++++--- tests/basics/bytearray_construct_endian.py | 9 ++++++--- tests/basics/bytes_add_array.py | 9 ++++++--- tests/basics/bytes_add_endian.py | 9 ++++++--- tests/basics/bytes_compare_array.py | 9 ++++++--- tests/basics/bytes_construct_array.py | 9 ++++++--- tests/basics/bytes_construct_endian.py | 9 ++++++--- tests/basics/memoryview1.py | 9 ++++++++- tests/basics/memoryview2.py | 9 ++++++++- tests/basics/memoryview_intbig.py | 9 ++++++++- tests/basics/memoryview_itemsize.py | 9 ++++++++- tests/float/array_construct.py | 9 ++++++--- tests/float/bytearray_construct.py | 9 ++++++--- tests/float/bytes_construct.py | 9 ++++++--- tests/float/float_array.py | 9 ++++++--- tests/inlineasm/asmfpldrstr.py | 2 +- tests/inlineasm/asmsum.py | 2 +- tests/micropython/heapalloc_iter.py | 11 +++++++++-- tests/misc/non_compliant.py | 2 +- 26 files changed, 152 insertions(+), 63 deletions(-) diff --git a/tests/basics/array1.py b/tests/basics/array1.py index bad879035c2d0..3370c240d3737 100644 --- a/tests/basics/array1.py +++ b/tests/basics/array1.py @@ -1,8 +1,11 @@ try: - import array + import uarray as array except ImportError: - print("SKIP") - raise SystemExit + try: + import array + except ImportError: + print("SKIP") + raise SystemExit a = array.array('B', [1, 2, 3]) print(a, len(a)) diff --git a/tests/basics/array_add.py b/tests/basics/array_add.py index 76ce59f761e06..8335eb6b82bb9 100644 --- a/tests/basics/array_add.py +++ b/tests/basics/array_add.py @@ -1,9 +1,12 @@ # test array + array try: - import array + import uarray as array except ImportError: - print("SKIP") - raise SystemExit + try: + import array + except ImportError: + print("SKIP") + raise SystemExit a1 = array.array('I', [1]) a2 = array.array('I', [2]) diff --git a/tests/basics/array_construct.py b/tests/basics/array_construct.py index 2221de99068c2..4985244d13bb5 100644 --- a/tests/basics/array_construct.py +++ b/tests/basics/array_construct.py @@ -1,10 +1,13 @@ # test construction of array.array from different objects try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit # tuple, list print(array('b', (1, 2))) diff --git a/tests/basics/array_construct2.py b/tests/basics/array_construct2.py index c305b7f011d1f..d1b1e9d158c63 100644 --- a/tests/basics/array_construct2.py +++ b/tests/basics/array_construct2.py @@ -1,8 +1,11 @@ try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit # construct from something with unknown length (requires generators) print(array('i', (i for i in range(10)))) diff --git a/tests/basics/array_construct_endian.py b/tests/basics/array_construct_endian.py index 990d7b1ea039b..82a962fbe0d57 100644 --- a/tests/basics/array_construct_endian.py +++ b/tests/basics/array_construct_endian.py @@ -1,10 +1,13 @@ # test construction of array.array from different objects try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit # raw copy from bytes, bytearray print(array('h', b'12')) diff --git a/tests/basics/array_intbig.py b/tests/basics/array_intbig.py index 5702a8ae63538..ba7f9ef985ad3 100644 --- a/tests/basics/array_intbig.py +++ b/tests/basics/array_intbig.py @@ -1,10 +1,13 @@ # test array types QqLl that require big-ints try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit print(array('L', [0, 2**32-1])) print(array('l', [-2**31, 0, 2**31-1])) diff --git a/tests/basics/array_micropython.py b/tests/basics/array_micropython.py index e26ad7ae9693e..6b3dc7a93b151 100644 --- a/tests/basics/array_micropython.py +++ b/tests/basics/array_micropython.py @@ -1,9 +1,12 @@ # test MicroPython-specific features of array.array try: - import array + import uarray as array except ImportError: - print("SKIP") - raise SystemExit + try: + import array + except ImportError: + print("SKIP") + raise SystemExit # arrays of objects a = array.array('O') diff --git a/tests/basics/bytearray_construct_array.py b/tests/basics/bytearray_construct_array.py index bde5fa08bd2c2..52eaa7c6efbdc 100644 --- a/tests/basics/bytearray_construct_array.py +++ b/tests/basics/bytearray_construct_array.py @@ -1,9 +1,12 @@ # test construction of bytearray from different objects try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit # arrays print(bytearray(array('b', [1, 2]))) diff --git a/tests/basics/bytearray_construct_endian.py b/tests/basics/bytearray_construct_endian.py index 0002f19c5f9ba..332b43e68617b 100644 --- a/tests/basics/bytearray_construct_endian.py +++ b/tests/basics/bytearray_construct_endian.py @@ -1,9 +1,12 @@ # test construction of bytearray from different objects try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit # arrays print(bytearray(array('h', [1, 2]))) diff --git a/tests/basics/bytes_add_array.py b/tests/basics/bytes_add_array.py index b17556d83cbaf..c6382bed7495c 100644 --- a/tests/basics/bytes_add_array.py +++ b/tests/basics/bytes_add_array.py @@ -1,9 +1,12 @@ # test bytes + other try: - import array + import uarray as array except ImportError: - print("SKIP") - raise SystemExit + try: + import array + except ImportError: + print("SKIP") + raise SystemExit # should be byteorder-neutral print(b"123" + array.array('h', [0x1515])) diff --git a/tests/basics/bytes_add_endian.py b/tests/basics/bytes_add_endian.py index 8cfffa7b6ace2..40b3de7d61520 100644 --- a/tests/basics/bytes_add_endian.py +++ b/tests/basics/bytes_add_endian.py @@ -1,8 +1,11 @@ # test bytes + other try: - import array + import uarray as array except ImportError: - print("SKIP") - raise SystemExit + try: + import array + except ImportError: + print("SKIP") + raise SystemExit print(b"123" + array.array('i', [1])) diff --git a/tests/basics/bytes_compare_array.py b/tests/basics/bytes_compare_array.py index ad378de70c56b..6bad50b55a1ed 100644 --- a/tests/basics/bytes_compare_array.py +++ b/tests/basics/bytes_compare_array.py @@ -1,8 +1,11 @@ try: - import array + import uarray as array except ImportError: - print("SKIP") - raise SystemExit + try: + import array + except ImportError: + print("SKIP") + raise SystemExit print(array.array('b', [1, 2]) in b'\x01\x02\x03') # CPython gives False here diff --git a/tests/basics/bytes_construct_array.py b/tests/basics/bytes_construct_array.py index 453eb59010392..7bdd8f10df4de 100644 --- a/tests/basics/bytes_construct_array.py +++ b/tests/basics/bytes_construct_array.py @@ -1,9 +1,12 @@ # test construction of bytes from different objects try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit # arrays print(bytes(array('b', [1, 2]))) diff --git a/tests/basics/bytes_construct_endian.py b/tests/basics/bytes_construct_endian.py index cf1a9f408fa8d..294c5f23f5cff 100644 --- a/tests/basics/bytes_construct_endian.py +++ b/tests/basics/bytes_construct_endian.py @@ -1,10 +1,13 @@ # test construction of bytes from different objects try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit # arrays print(bytes(array('h', [1, 2]))) diff --git a/tests/basics/memoryview1.py b/tests/basics/memoryview1.py index a0ac9e344932d..b5314f3e99e9f 100644 --- a/tests/basics/memoryview1.py +++ b/tests/basics/memoryview1.py @@ -4,6 +4,14 @@ except: print("SKIP") raise SystemExit +try: + import uarray as array +except ImportError: + try: + import array + except ImportError: + print("SKIP") + raise SystemExit # test reading from bytes b = b'1234' @@ -39,7 +47,6 @@ print(bytearray(m)) print(list(memoryview(memoryview(b'1234')))) # read-only memoryview -import array a = array.array('i', [1, 2, 3, 4]) m = memoryview(a) print(list(m)) diff --git a/tests/basics/memoryview2.py b/tests/basics/memoryview2.py index 06a7be59fdbd1..eacc227c28317 100644 --- a/tests/basics/memoryview2.py +++ b/tests/basics/memoryview2.py @@ -1,10 +1,17 @@ # test memoryview accessing maximum values for signed/unsigned elements try: - from array import array memoryview except: print("SKIP") raise SystemExit +try: + from uarray import array +except ImportError: + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit print(list(memoryview(b'\x7f\x80\x81\xff'))) print(list(memoryview(array('b', [0x7f, -0x80])))) diff --git a/tests/basics/memoryview_intbig.py b/tests/basics/memoryview_intbig.py index a76d9cbec705e..4800a70cc2726 100644 --- a/tests/basics/memoryview_intbig.py +++ b/tests/basics/memoryview_intbig.py @@ -1,10 +1,17 @@ # test memoryview accessing maximum values for signed/unsigned elements try: - from array import array memoryview except: print("SKIP") raise SystemExit +try: + from uarray import array +except ImportError: + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit print(list(memoryview(array('i', [0x7f000000, -0x80000000])))) print(list(memoryview(array('I', [0x7f000000, 0x80000000, 0x81000000, 0xffffffff])))) diff --git a/tests/basics/memoryview_itemsize.py b/tests/basics/memoryview_itemsize.py index 60cb823087c45..cd7a87c23dfea 100644 --- a/tests/basics/memoryview_itemsize.py +++ b/tests/basics/memoryview_itemsize.py @@ -1,9 +1,16 @@ try: memoryview(b'a').itemsize - from array import array except: print("SKIP") raise SystemExit +try: + from uarray import array +except ImportError: + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit for code in ['b', 'h', 'i', 'l', 'q', 'f', 'd']: print(memoryview(array(code)).itemsize) diff --git a/tests/float/array_construct.py b/tests/float/array_construct.py index 938675835bbcf..eb735c67c33a4 100644 --- a/tests/float/array_construct.py +++ b/tests/float/array_construct.py @@ -1,10 +1,13 @@ # test construction of array from array with float type try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit print(array('f', array('h', [1, 2]))) print(array('d', array('f', [1, 2]))) diff --git a/tests/float/bytearray_construct.py b/tests/float/bytearray_construct.py index e960d624ec8ca..4e7631b2b9214 100644 --- a/tests/float/bytearray_construct.py +++ b/tests/float/bytearray_construct.py @@ -1,9 +1,12 @@ # test construction of bytearray from array with float type try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit print(bytearray(array('f', [1, 2.3]))) diff --git a/tests/float/bytes_construct.py b/tests/float/bytes_construct.py index 0e4482e436698..96294659bfc0f 100644 --- a/tests/float/bytes_construct.py +++ b/tests/float/bytes_construct.py @@ -1,9 +1,12 @@ # test construction of bytearray from array with float type try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit print(bytes(array('f', [1, 2.3]))) diff --git a/tests/float/float_array.py b/tests/float/float_array.py index 8c8edcff7c86b..0c7f1b3adeb05 100644 --- a/tests/float/float_array.py +++ b/tests/float/float_array.py @@ -1,8 +1,11 @@ try: - from array import array + from uarray import array except ImportError: - print("SKIP") - raise SystemExit + try: + from array import array + except ImportError: + print("SKIP") + raise SystemExit def test(a): print(a) diff --git a/tests/inlineasm/asmfpldrstr.py b/tests/inlineasm/asmfpldrstr.py index 8fa9af6369568..0efb50bb0e31a 100644 --- a/tests/inlineasm/asmfpldrstr.py +++ b/tests/inlineasm/asmfpldrstr.py @@ -1,4 +1,4 @@ -import array +import uarray as array @micropython.asm_thumb # test vldr, vstr def arrayadd(r0): vldr(s0, [r0, 0]) diff --git a/tests/inlineasm/asmsum.py b/tests/inlineasm/asmsum.py index 9cbd8418eab54..93d8eec8dcf6a 100644 --- a/tests/inlineasm/asmsum.py +++ b/tests/inlineasm/asmsum.py @@ -46,7 +46,7 @@ def asm_sum_bytes(r0, r1): mov(r0, r2) -import array +import uarray as array b = array.array('l', (100, 200, 300, 400)) n = asm_sum_words(len(b), b) diff --git a/tests/micropython/heapalloc_iter.py b/tests/micropython/heapalloc_iter.py index 163e1721115dc..5a44a558bbfe5 100644 --- a/tests/micropython/heapalloc_iter.py +++ b/tests/micropython/heapalloc_iter.py @@ -1,10 +1,17 @@ # test that iterating doesn't use the heap try: frozenset - import array -except (NameError, ImportError): +except NameError: print("SKIP") raise SystemExit +try: + import uarray as array +except ImportError: + try: + import array + except ImportError: + print("SKIP") + raise SystemExit try: from micropython import heap_lock, heap_unlock diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index 580583bf39c32..ea67382227aef 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -1,7 +1,7 @@ # tests for things that are not implemented, or have non-compliant behaviour try: - import array + import uarray as array import ustruct except ImportError: print("SKIP") From b02d7e612d12b507a3a91a95eb30187b24ce21a7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 22 Oct 2019 17:03:59 +1100 Subject: [PATCH 0619/1299] extmod/modbluetooth: Rename module to "ubluetooth". For consistency with "umachine". Now that weak links are enabled by default for built-in modules, this should be a no-op, but allows extension of the bluetooth module by user code. Also move registration of ubluetooth to objmodule rather than port-specific. --- extmod/modbluetooth.c | 4 ++-- ports/esp32/mpconfigport.h | 8 -------- ports/stm32/mpconfigport.h | 8 -------- py/builtin.h | 1 + py/objmodule.c | 3 +++ 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 2a3e87bc2489c..d1a7d576e183f 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -645,7 +645,7 @@ STATIC const mp_obj_type_t bluetooth_ble_type = { }; STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bluetooth) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluetooth) }, { MP_ROM_QSTR(MP_QSTR_BLE), MP_ROM_PTR(&bluetooth_ble_type) }, { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bluetooth_uuid_type) }, { MP_ROM_QSTR(MP_QSTR_FLAG_READ), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) }, @@ -655,7 +655,7 @@ STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = { STATIC MP_DEFINE_CONST_DICT(mp_module_bluetooth_globals, mp_module_bluetooth_globals_table); -const mp_obj_module_t mp_module_bluetooth = { +const mp_obj_module_t mp_module_ubluetooth = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_bluetooth_globals, }; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 89e5373472b3a..6cf86446b2c0b 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -191,15 +191,8 @@ extern const struct _mp_obj_module_t uos_module; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_network; -extern const struct _mp_obj_module_t mp_module_bluetooth; extern const struct _mp_obj_module_t mp_module_onewire; -#if MICROPY_PY_BLUETOOTH -#define BLUETOOTH_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_bluetooth), MP_ROM_PTR(&mp_module_bluetooth) }, -#else -#define BLUETOOTH_BUILTIN_MODULE -#endif - #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \ @@ -208,7 +201,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ - BLUETOOTH_BUILTIN_MODULE \ { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 2cc37e3bf2bf4..b31eed29326f2 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -211,7 +211,6 @@ extern const struct _mp_obj_module_t mp_module_uos; extern const struct _mp_obj_module_t mp_module_utime; extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_network; -extern const struct _mp_obj_module_t mp_module_bluetooth; extern const struct _mp_obj_module_t mp_module_onewire; #if MICROPY_PY_STM @@ -237,12 +236,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; #define NETWORK_BUILTIN_MODULE #endif -#if MICROPY_PY_BLUETOOTH -#define BLUETOOTH_BUILTIN_MODULE { MP_ROM_QSTR(MP_QSTR_bluetooth), MP_ROM_PTR(&mp_module_bluetooth) }, -#else -#define BLUETOOTH_BUILTIN_MODULE -#endif - #define MICROPY_PORT_BUILTIN_MODULES \ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&machine_module) }, \ { MP_ROM_QSTR(MP_QSTR_pyb), MP_ROM_PTR(&pyb_module) }, \ @@ -251,7 +244,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_utime) }, \ SOCKET_BUILTIN_MODULE \ NETWORK_BUILTIN_MODULE \ - BLUETOOTH_BUILTIN_MODULE \ { MP_ROM_QSTR(MP_QSTR__onewire), MP_ROM_PTR(&mp_module_onewire) }, \ // extra constants diff --git a/py/builtin.h b/py/builtin.h index 1928577be864e..2dbe8a782092c 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -122,6 +122,7 @@ extern const mp_obj_module_t mp_module_uwebsocket; extern const mp_obj_module_t mp_module_webrepl; extern const mp_obj_module_t mp_module_framebuf; extern const mp_obj_module_t mp_module_btree; +extern const mp_obj_module_t mp_module_ubluetooth; extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; diff --git a/py/objmodule.c b/py/objmodule.c index d725bb6a14537..81558a02eff77 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -224,6 +224,9 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = { #if MICROPY_PY_BTREE { MP_ROM_QSTR(MP_QSTR_btree), MP_ROM_PTR(&mp_module_btree) }, #endif +#if MICROPY_PY_BLUETOOTH + { MP_ROM_QSTR(MP_QSTR_ubluetooth), MP_ROM_PTR(&mp_module_ubluetooth) }, +#endif // extra builtin modules as defined by a port MICROPY_PORT_BUILTIN_MODULES From 19e87742c41e7732258ea06406039be7a734e890 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 22 Oct 2019 17:05:36 +1100 Subject: [PATCH 0620/1299] docs/library/bluetooth: Rename to "ubluetooth". --- docs/library/index.rst | 2 +- docs/library/{bluetooth.rst => ubluetooth.rst} | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) rename docs/library/{bluetooth.rst => ubluetooth.rst} (96%) diff --git a/docs/library/index.rst b/docs/library/index.rst index 223304881a758..a2d11dee7f2f3 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -74,13 +74,13 @@ it will fallback to loading the built-in ``ujson`` module. :maxdepth: 1 builtins.rst - bluetooth.rst cmath.rst gc.rst math.rst sys.rst uarray.rst ubinascii.rst + ubluetooth.rst ucollections.rst uerrno.rst uhashlib.rst diff --git a/docs/library/bluetooth.rst b/docs/library/ubluetooth.rst similarity index 96% rename from docs/library/bluetooth.rst rename to docs/library/ubluetooth.rst index e672cef927402..831c64a95f859 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -1,7 +1,7 @@ -:mod:`bluetooth` --- low-level Bluetooth -======================================== +:mod:`ubluetooth` --- low-level Bluetooth +========================================= -.. module:: bluetooth +.. module:: ubluetooth :synopsis: Low-level Bluetooth radio functionality This module provides an interface to a Bluetooth controller on a board. @@ -123,7 +123,7 @@ The event codes are:: _IRQ_GATTC_INDICATE = const(1 << 14) In order to save space in the firmware, these constants are not included on the -:mod:`bluetooth` module. Add the ones that you need from the list above to your +:mod:`ubluetooth` module. Add the ones that you need from the list above to your program. @@ -203,8 +203,8 @@ writes from a central to a given characteristic, use value. The **flags** are a bitwise-OR combination of the - :data:`bluetooth.FLAGS_READ`, :data:`bluetooth.FLAGS_WRITE` and - :data:`bluetooth.FLAGS_NOTIFY` values defined below. + :data:`ubluetooth.FLAGS_READ`, :data:`bluetooth.FLAGS_WRITE` and + :data:`ubluetooth.FLAGS_NOTIFY` values defined below. The return value is a list (one element per service) of tuples (each element is a value handle). Characteristics and descriptor handles are flattened @@ -321,6 +321,6 @@ Constructor Constants --------- -.. data:: bluetooth.FLAG_READ - bluetooth.FLAG_WRITE - bluetooth.FLAG_NOTIFY +.. data:: ubluetooth.FLAG_READ + ubluetooth.FLAG_WRITE + ubluetooth.FLAG_NOTIFY From 19ca025b45b3160a2ad5a20014cdd7bf0053ff9d Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 21 Oct 2019 11:43:22 +1100 Subject: [PATCH 0621/1299] stm32/sdram: Fix to use new mpu_config_start/mpu_config_end signature. --- ports/stm32/sdram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c index 5d54dc2cb33cf..7e7e1d7641899 100644 --- a/ports/stm32/sdram.c +++ b/ports/stm32/sdram.c @@ -248,10 +248,10 @@ static void sdram_init_seq(SDRAM_HandleTypeDef Initially disable all access for the entire SDRAM memory space, then enable access/caching for the size used */ - mpu_config_start(); + uint32_t irq_state = mpu_config_start(); mpu_config_region(MPU_REGION_SDRAM1, SDRAM_START_ADDRESS, MPU_CONFIG_DISABLE(0x00, MPU_REGION_SIZE_512MB)); mpu_config_region(MPU_REGION_SDRAM2, SDRAM_START_ADDRESS, MPU_CONFIG_SDRAM(SDRAM_MPU_REGION_SIZE)); - mpu_config_end(); + mpu_config_end(irq_state); #endif } From 079cc940a68b3b3b9d47d4402267393a528a0477 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Thu, 22 Aug 2019 10:21:48 +1000 Subject: [PATCH 0622/1299] powerpc: Add initial port to bare metal PowerPC arch. Runs in microwatt (GHDL and FPGA) and qemu. Port done initially by Michael Neuling, with help from Anton Blanchard and Jordan Niethe. --- .travis.yml | 9 +++ ports/powerpc/Makefile | 64 +++++++++++++++ ports/powerpc/README.md | 40 +++++++++ ports/powerpc/frozentest.mpy | Bin 0 -> 196 bytes ports/powerpc/frozentest.py | 7 ++ ports/powerpc/head.S | 121 +++++++++++++++++++++++++++ ports/powerpc/main.c | 139 ++++++++++++++++++++++++++++++++ ports/powerpc/mpconfigport.h | 123 ++++++++++++++++++++++++++++ ports/powerpc/mphalport.h | 45 +++++++++++ ports/powerpc/powerpc.lds | 13 +++ ports/powerpc/qstrdefsport.h | 1 + ports/powerpc/uart_core.c | 73 +++++++++++++++++ ports/powerpc/uart_lpc_serial.c | 111 +++++++++++++++++++++++++ ports/powerpc/uart_lpc_serial.h | 29 +++++++ ports/powerpc/uart_potato.c | 121 +++++++++++++++++++++++++++ ports/powerpc/uart_potato.h | 29 +++++++ ports/powerpc/unistd.h | 36 +++++++++ py/nlr.h | 4 + py/nlrpowerpc.c | 121 +++++++++++++++++++++++++++ py/py.mk | 1 + 20 files changed, 1087 insertions(+) create mode 100644 ports/powerpc/Makefile create mode 100644 ports/powerpc/README.md create mode 100644 ports/powerpc/frozentest.mpy create mode 100644 ports/powerpc/frozentest.py create mode 100644 ports/powerpc/head.S create mode 100644 ports/powerpc/main.c create mode 100644 ports/powerpc/mpconfigport.h create mode 100644 ports/powerpc/mphalport.h create mode 100644 ports/powerpc/powerpc.lds create mode 100644 ports/powerpc/qstrdefsport.h create mode 100644 ports/powerpc/uart_core.c create mode 100644 ports/powerpc/uart_lpc_serial.c create mode 100644 ports/powerpc/uart_lpc_serial.h create mode 100644 ports/powerpc/uart_potato.c create mode 100644 ports/powerpc/uart_potato.h create mode 100644 ports/powerpc/unistd.h create mode 100644 py/nlrpowerpc.c diff --git a/.travis.yml b/.travis.yml index 077fca20afad5..5923cb2b96b8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -232,3 +232,12 @@ jobs: - sudo apt-get install libnewlib-arm-none-eabi script: - make ${MAKEOPTS} -C ports/teensy + + # powerpc port + - stage: test + env: NAME="powerpc port build" + install: + - sudo apt-get install gcc-powerpc64le-linux-gnu + - sudo apt-get install libc6-dev-ppc64el-cross + script: + - make ${MAKEOPTS} -C ports/powerpc CROSS_COMPILE=powerpc64le-linux-gnu- diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile new file mode 100644 index 0000000000000..30474df1d1673 --- /dev/null +++ b/ports/powerpc/Makefile @@ -0,0 +1,64 @@ +include ../../py/mkenv.mk + +# qstr definitions (must come before including py.mk) +QSTR_DEFS = qstrdefsport.h + +# include py core make definitions +include $(TOP)/py/py.mk + +ARCH = $(shell uname -m) +ifneq ("$(ARCH)", "ppc64") +ifneq ("$(ARCH)", "ppc64le") + CROSS_COMPILE = powerpc64le-linux- +endif +endif + +INC += -I. +INC += -I$(TOP) +INC += -I$(BUILD) + +CFLAGS = $(INC) -g -Wall -std=c99 $(COPT) +CFLAGS += -mno-string -mno-multiple -mno-vsx -mno-altivec -nostdlib +CFLAGS += -mlittle-endian -mstrict-align -msoft-float +CFLAGS += -Os +CFLAGS += -fdata-sections -ffunction-sections -fno-stack-protector -ffreestanding +CFLAGS += -U_FORTIFY_SOURCE + +LDFLAGS = -N -T powerpc.lds -nostdlib + +LIBS = + +SRC_C = \ + main.c \ + uart_core.c \ + uart_potato.c \ + uart_lpc_serial.c \ + lib/utils/printf.c \ + lib/utils/stdout_helpers.c \ + lib/utils/pyexec.c \ + lib/libc/string0.c \ + lib/mp-readline/readline.c \ + $(BUILD)/_frozen_mpy.c \ + +OBJ = $(PY_CORE_O) +OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(BUILD)/head.o + +all: $(BUILD)/firmware.elf $(BUILD)/firmware.map $(BUILD)/firmware.bin + +$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h + $(ECHO) "MISC freezing bytecode" + $(Q)$(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=mpz $< > $@ + +$(BUILD)/firmware.elf: $(OBJ) powerpc.lds + $(ECHO) "LINK $@" + $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) + $(Q)$(SIZE) $@ + +$(BUILD)/firmware.bin: $(BUILD)/firmware.elf + $(Q)$(OBJCOPY) -O binary $^ $(BUILD)/firmware.bin + +$(BUILD)/firmware.map: $(BUILD)/firmware.elf + $(Q)nm $^ | sort > $(BUILD)/firmware.map + +include $(TOP)/py/mkrules.mk diff --git a/ports/powerpc/README.md b/ports/powerpc/README.md new file mode 100644 index 0000000000000..862bfcd3c5002 --- /dev/null +++ b/ports/powerpc/README.md @@ -0,0 +1,40 @@ +# The PowerPC port that runs on microwatt and qemu + +This port is intended to be a minimal MicroPython port that runs in +QEMU, microwatt simulator with ghdl or microwatt on Xilinx FPGA with +potato UART. + +## Building + +By default the port will be built for the host machine: + + $ make + +## Cross compilation for POWERPC + +If you need to cross compilers you'll want to grab a powerpc64le +compiler (not powerpc or powerpc64). + +On Ubuntu (18.04) you'll want: + + $ apt install gcc-powerpc64le-linux-gnu + +*(Use CROSS_COMPILE=powerpc64le-linux-gnu-)* + +If your distro doesn't have cross compilers, you can get cross compilers here: +- https://toolchains.bootlin.com/ +*(use CROSS_COMPILE=powerpc64le-buildroot-linux-gnu-)* + +(Avoid musl libc as it defines __assert_fail() differently to glibc +which breaks the micropython powerpc code) + +Then do: + + $ make CROSS_COMPILE= + +Building will produce the build/firmware.bin file which can be used +QEMU or [microwatt](https://github.com/antonblanchard/microwatt). + +To run in QEMU use: + + $ ./qemu-system-ppc64 -M powernv -cpu POWER9 -nographic -bios build/firmware.bin diff --git a/ports/powerpc/frozentest.mpy b/ports/powerpc/frozentest.mpy new file mode 100644 index 0000000000000000000000000000000000000000..8a89194a1048700453ca5b682c972e131a878610 GIT binary patch literal 196 zcmeZeWs+BD3K0-vV3$fO%CAbzD@iRb(JQFb)X>n-)?g51s1{%=4X89>j07^38K5*H zlxBj^O1s|A5(P3FocJ5U#h5aIN(Dhm8lQ%@Tz7t59~qd;%uuY9sF0JNm#$D;Qj`g# zN-`2l6f%ny^74Tc(AuKB)RbbiL=@?a#A1cgyv*eMlvIUt8_#Vzw^<=MBeAGBi94wh M=uibiBV!Xr0D7G~UjP6A literal 0 HcmV?d00001 diff --git a/ports/powerpc/frozentest.py b/ports/powerpc/frozentest.py new file mode 100644 index 0000000000000..0f99b74297fbb --- /dev/null +++ b/ports/powerpc/frozentest.py @@ -0,0 +1,7 @@ +print('uPy') +print('a long string that is not interned') +print('a string that has unicode αβγ chars') +print(b'bytes 1234\x01') +print(123456789) +for i in range(4): + print(i) diff --git a/ports/powerpc/head.S b/ports/powerpc/head.S new file mode 100644 index 0000000000000..09aa62e59ca85 --- /dev/null +++ b/ports/powerpc/head.S @@ -0,0 +1,121 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * 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. + */ + +#define STACK_TOP 0x60000 + +#define FIXUP_ENDIAN \ + tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ + b 191f; /* Skip trampoline if endian is good */ \ + .long 0xa600607d; /* mfmsr r11 */ \ + .long 0x01006b69; /* xori r11,r11,1 */ \ + .long 0x05009f42; /* bcl 20,31,$+4 */ \ + .long 0xa602487d; /* mflr r10 */ \ + .long 0x14004a39; /* addi r10,r10,20 */ \ + .long 0xa64b5a7d; /* mthsrr0 r10 */ \ + .long 0xa64b7b7d; /* mthsrr1 r11 */ \ + .long 0x2402004c; /* hrfid */ \ + 191: + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + +.section ".head","ax" + +/* + * Microwatt comes in at 0 as little endian so we do not need to worry up + * FIXUP_ENDIAN. + */ + . = 0 + .global _start +_start: + b boot_entry + +/* QEMU comes in at 0x10. Put a value in argc/r3 to distingush from + * microwatt. */ + . = 0x10 + FIXUP_ENDIAN + LOAD_IMM64(%r3, 1) + b boot_entry + + .global boot_entry + boot_entry: + /* Save R3 to non-volatile register */ + mr %r14, %r3 + restart: + /* + * setup stack with a safety gap, since we might write to the + * previous frame. + */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r12, main) + mtctr %r12 + bctrl + + /* On exit, restart */ + mr %r3, %r14 + b restart + +#define EXCEPTION(nr) \ + .= nr; \ +b . + + /* More exception stubs */ + EXCEPTION(0x300) + EXCEPTION(0x380) + EXCEPTION(0x400) + EXCEPTION(0x480) + EXCEPTION(0x500) + EXCEPTION(0x600) + EXCEPTION(0x700) + EXCEPTION(0x800) + EXCEPTION(0x900) + EXCEPTION(0x980) + EXCEPTION(0xa00) + EXCEPTION(0xb00) + EXCEPTION(0xc00) + EXCEPTION(0xd00) + EXCEPTION(0xe00) + EXCEPTION(0xe20) + EXCEPTION(0xe40) + EXCEPTION(0xe60) + EXCEPTION(0xe80) + EXCEPTION(0xf00) + EXCEPTION(0xf20) + EXCEPTION(0xf40) + EXCEPTION(0xf60) + EXCEPTION(0xf80) + EXCEPTION(0x1000) + EXCEPTION(0x1100) + EXCEPTION(0x1200) + EXCEPTION(0x1300) + EXCEPTION(0x1400) + EXCEPTION(0x1500) + EXCEPTION(0x1600) diff --git a/ports/powerpc/main.c b/ports/powerpc/main.c new file mode 100644 index 0000000000000..9b164ac18c731 --- /dev/null +++ b/ports/powerpc/main.c @@ -0,0 +1,139 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/compile.h" +#include "py/runtime.h" +#include "py/repl.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/stackctrl.h" +#include "lib/utils/pyexec.h" + +void __stack_chk_fail(void); +void __stack_chk_fail(void) { + static bool failed_once; + + if (failed_once) { + return; + } + failed_once = true; + printf("Stack corruption detected !\n"); + assert(0); +} + +/* fill in __assert_fail for libc */ +void __assert_fail(const char *__assertion, const char *__file, + unsigned int __line, const char *__function) { + printf("Assert at %s:%d:%s() \"%s\" failed\n", __file, __line, __function, __assertion); + for (;;) ; +} + +static char *stack_top; +#if MICROPY_ENABLE_GC +static char heap[32 * 1024]; +#endif + +extern void uart_init_ppc(int qemu); + +int main(int argc, char **argv) { + int stack_dummy; + stack_top = (char*)&stack_dummy; + + // microwatt has argc/r3 = 0 whereas QEMU has r3 set in head.S + uart_init_ppc(argc); + + #if MICROPY_ENABLE_PYSTACK + static mp_obj_t pystack[1024]; + mp_pystack_init(pystack, &pystack[1024]); + #endif + + #if MICROPY_STACK_CHECK + mp_stack_ctrl_init(); + mp_stack_set_limit(48 * 1024); + #endif + + #if MICROPY_ENABLE_GC + gc_init(heap, heap + sizeof(heap)); + #endif + mp_init(); + #if MICROPY_ENABLE_COMPILER + #if MICROPY_REPL_EVENT_DRIVEN + pyexec_event_repl_init(); + for (;;) { + int c = mp_hal_stdin_rx_chr(); + if (pyexec_event_repl_process_char(c)) { + break; + } + } + #else + pyexec_friendly_repl(); + #endif + #else + pyexec_frozen_module("frozentest.py"); + #endif + mp_deinit(); + return 0; +} + +void gc_collect(void) { + // WARNING: This gc_collect implementation doesn't try to get root + // pointers from CPU registers, and thus may function incorrectly. + void *dummy; + gc_collect_start(); + gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); + gc_collect_end(); + gc_dump_info(); +} + +mp_lexer_t *mp_lexer_new_from_file(const char *filename) { + mp_raise_OSError(MP_ENOENT); +} + +mp_import_stat_t mp_import_stat(const char *path) { + return MP_IMPORT_STAT_NO_EXIST; +} + +mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); + +void nlr_jump_fail(void *val) { + while (1); +} + +void NORETURN __fatal_error(const char *msg) { + while (1); +} + +#ifndef NDEBUG +void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { + printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); + __fatal_error("Assertion failed"); +} +#endif diff --git a/ports/powerpc/mpconfigport.h b/ports/powerpc/mpconfigport.h new file mode 100644 index 0000000000000..93ef699ad90cb --- /dev/null +++ b/ports/powerpc/mpconfigport.h @@ -0,0 +1,123 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * 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 + +// options to control how MicroPython is built + +// You can disable the built-in MicroPython compiler by setting the following +// config option to 0. If you do this then you won't get a REPL prompt, but you +// will still be able to execute pre-compiled scripts, compiled with mpy-cross. +#define MICROPY_ENABLE_COMPILER (1) + +//#define MICROPY_DEBUG_VERBOSE (1) + +#define MICROPY_QSTR_BYTES_IN_HASH (1) +#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool +#define MICROPY_ALLOC_PATH_MAX (256) +#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16) +#define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_COMP_MODULE_CONST (0) +#define MICROPY_COMP_CONST (0) +#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) +#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) +#define MICROPY_MEM_STATS (0) +#define MICROPY_DEBUG_PRINTERS (1) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_STACK_CHECK (1) +#define MICROPY_GC_ALLOC_THRESHOLD (0) +#define MICROPY_REPL_EVENT_DRIVEN (0) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_HELPER_LEXER_UNIX (0) +#define MICROPY_ENABLE_SOURCE_LINE (1) +#define MICROPY_ENABLE_DOC_STRING (0) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE) +#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0) +#define MICROPY_PY_ASYNC_AWAIT (0) +#define MICROPY_MODULE_BUILTIN_INIT (1) +#define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_PY_BUILTINS_DICT_FROMKEYS (1) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_BUILTINS_ENUMERATE (1) +#define MICROPY_PY_BUILTINS_FILTER (1) +#define MICROPY_PY_BUILTINS_FROZENSET (1) +#define MICROPY_PY_BUILTINS_REVERSED (1) +#define MICROPY_PY_BUILTINS_SET (1) +#define MICROPY_PY_BUILTINS_SLICE (1) +#define MICROPY_PY_BUILTINS_PROPERTY (1) +#define MICROPY_PY_BUILTINS_MIN_MAX (1) +#define MICROPY_PY_BUILTINS_STR_COUNT (1) +#define MICROPY_PY_BUILTINS_STR_OP_MODULO (1) +#define MICROPY_PY_BUILTINS_HELP (1) +#define MICROPY_PY_BUILTINS_HELP_MODULES (1) +#define MICROPY_PY___FILE__ (0) +#define MICROPY_PY_GC (1) +#define MICROPY_PY_ARRAY (1) +#define MICROPY_PY_COLLECTIONS (1) +#define MICROPY_PY_MATH (0) +#define MICROPY_PY_CMATH (0) +#define MICROPY_PY_IO (0) +#define MICROPY_PY_STRUCT (1) +#define MICROPY_PY_SYS (1) +#define MICROPY_MODULE_FROZEN_MPY (1) +#define MICROPY_CPYTHON_COMPAT (0) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#define MICROPY_ENABLE_PYSTACK (1) +#define MICROPY_USE_INTERNAL_PRINTF (1) + +// type definitions for the specific machine + +#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) + +// This port is 64-bit +#define UINT_FMT "%lu" +#define INT_FMT "%ld" +typedef signed long mp_int_t; // must be pointer size +typedef unsigned long mp_uint_t; // must be pointer size + +typedef long mp_off_t; + +#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) + +// extra built in names to add to the global namespace +#define MICROPY_PORT_BUILTINS \ + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, + +#define MICROPY_HW_BOARD_NAME "bare-metal" +#define MICROPY_HW_MCU_NAME "POWERPC" + +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[8]; + +// powerpc64 gcc doesn't seem to define these +// These are pointers, so make them 64 bit types +typedef long intptr_t; +typedef unsigned long uintptr_t; diff --git a/ports/powerpc/mphalport.h b/ports/powerpc/mphalport.h new file mode 100644 index 0000000000000..c6bf94007292e --- /dev/null +++ b/ports/powerpc/mphalport.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * 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. + */ + +#define mftb() ({unsigned long rval; \ + __asm__ volatile("mftb %0" : "=r" (rval)); rval;}) + +#define TBFREQ 512000000 + +static inline mp_uint_t mp_hal_ticks_ms(void) { + unsigned long tb = mftb(); + + return tb * 1000 / TBFREQ; +} + +static inline mp_uint_t mp_hal_ticks_us(void) { + unsigned long tb = mftb(); + + return tb * 1000000 / TBFREQ; +} + +static inline void mp_hal_set_interrupt_char(char c) { +} diff --git a/ports/powerpc/powerpc.lds b/ports/powerpc/powerpc.lds new file mode 100644 index 0000000000000..93bd8a605cbd2 --- /dev/null +++ b/ports/powerpc/powerpc.lds @@ -0,0 +1,13 @@ +SECTIONS +{ + . = 0; + _start = .; + .head : { + KEEP(*(.head)) + } + + /* Put this at 0x1700 which is right after our execption + * vectors in head.S. + */ + . = 0x1700; +} diff --git a/ports/powerpc/qstrdefsport.h b/ports/powerpc/qstrdefsport.h new file mode 100644 index 0000000000000..3ba897069bf73 --- /dev/null +++ b/ports/powerpc/qstrdefsport.h @@ -0,0 +1 @@ +// qstrs specific to this port diff --git a/ports/powerpc/uart_core.c b/ports/powerpc/uart_core.c new file mode 100644 index 0000000000000..b0dcd031a5ad2 --- /dev/null +++ b/ports/powerpc/uart_core.c @@ -0,0 +1,73 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/mpconfig.h" +#include "uart_potato.h" +#include "uart_lpc_serial.h" + +static int lpc_console; +static int potato_console; + +void uart_init_ppc(int lpc) { + lpc_console = lpc; + + if (!lpc_console) { + potato_console = 1; + + potato_uart_init(); + } else { + lpc_uart_init(); + } +} + +// Receive single character +int mp_hal_stdin_rx_chr(void) { + unsigned char c = 0; + if (lpc_console) { + c = lpc_uart_read(); + } else if (potato_console) { + c = potato_uart_read(); + } + return c; +} + +// Send string of given length +void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { + if (lpc_console) { + int i; + for (i = 0; i < len; i++) { + lpc_uart_write(str[i]); + } + } else if (potato_console) { + int i; + for (i = 0; i < len; i++) { + potato_uart_write(str[i]); + } + } +} diff --git a/ports/powerpc/uart_lpc_serial.c b/ports/powerpc/uart_lpc_serial.c new file mode 100644 index 0000000000000..51a55cb1e6571 --- /dev/null +++ b/ports/powerpc/uart_lpc_serial.c @@ -0,0 +1,111 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * 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 the LPC serial UART used by POWER9 boxes. This is modelled + * in the qemu POWER9 machine. + */ + +#include +#include +#include "py/mpconfig.h" + +#define PROC_FREQ 50000000 +#define UART_FREQ 115200 +#define UART_BASE 0xc0002000 +#define LPC_UART_BASE 0x60300d00103f8 + +/* Taken from skiboot */ +#define REG_RBR 0 +#define REG_THR 0 +#define REG_DLL 0 +#define REG_IER 1 +#define REG_DLM 1 +#define REG_FCR 2 +#define REG_IIR 2 +#define REG_LCR 3 +#define REG_MCR 4 +#define REG_LSR 5 +#define REG_MSR 6 +#define REG_SCR 7 + +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit holding register empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + +#define LCR_DLAB 0x80 /* DLL access */ + +#define IER_RX 0x01 +#define IER_THRE 0x02 +#define IER_ALL 0x0f + +static uint64_t lpc_uart_base; + +static void lpc_uart_reg_write(uint64_t offset, uint8_t val) { + uint64_t addr; + + addr = lpc_uart_base + offset; + + *(volatile uint8_t *)addr = val; +} + +static uint8_t lpc_uart_reg_read(uint64_t offset) { + uint64_t addr; + uint8_t val; + + addr = lpc_uart_base + offset; + + val = *(volatile uint8_t *)addr; + + return val; +} + +static int lpc_uart_tx_full(void) { + return !(lpc_uart_reg_read(REG_LSR) & LSR_THRE); +} + +static int lpc_uart_rx_empty(void) { + return !(lpc_uart_reg_read(REG_LSR) & LSR_DR); +} + +void lpc_uart_init(void) { + lpc_uart_base = LPC_UART_BASE; +} + +char lpc_uart_read(void) { + while (lpc_uart_rx_empty()) ; + return lpc_uart_reg_read(REG_THR); +} + +void lpc_uart_write(char c) { + while (lpc_uart_tx_full()); + lpc_uart_reg_write(REG_RBR, c); +} diff --git a/ports/powerpc/uart_lpc_serial.h b/ports/powerpc/uart_lpc_serial.h new file mode 100644 index 0000000000000..d0e35ca32bb5b --- /dev/null +++ b/ports/powerpc/uart_lpc_serial.h @@ -0,0 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * 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. + */ + +void lpc_uart_init(void); +char lpc_uart_read(void); +void lpc_uart_write(char c); diff --git a/ports/powerpc/uart_potato.c b/ports/powerpc/uart_potato.c new file mode 100644 index 0000000000000..18f89d463af5a --- /dev/null +++ b/ports/powerpc/uart_potato.c @@ -0,0 +1,121 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * 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 a driver for the potato UART used by the microwatt core. + * The original potato UART came from here + * https://github.com/skordal/potato + */ + +#include +#include +#include "py/mpconfig.h" + +#define PROC_FREQ 50000000 +#define UART_FREQ 115200 +#define POTATO_UART_BASE 0xc0002000 +uint64_t potato_uart_base; + +#define POTATO_CONSOLE_TX 0x00 +#define POTATO_CONSOLE_RX 0x08 +#define POTATO_CONSOLE_STATUS 0x10 +#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01 +#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02 +#define POTATO_CONSOLE_STATUS_RX_FULL 0x04 +#define POTATO_CONSOLE_STATUS_TX_FULL 0x08 +#define POTATO_CONSOLE_CLOCK_DIV 0x18 +#define POTATO_CONSOLE_IRQ_EN 0x20 + +static uint64_t potato_uart_reg_read(int offset) { + uint64_t addr; + uint64_t val; + + addr = potato_uart_base + offset; + + val = *(volatile uint64_t *)addr; + + return val; +} + +void potato_uart_reg_write(int offset, uint64_t val) { + uint64_t addr; + + addr = potato_uart_base + offset; + + *(volatile uint64_t *)addr = val; +} + +static int potato_uart_rx_empty(void) { + uint64_t val; + + val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); + + if (val & POTATO_CONSOLE_STATUS_RX_EMPTY) { + return 1; + } + + return 0; +} + +static int potato_uart_tx_full(void) { + uint64_t val; + + val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); + + if (val & POTATO_CONSOLE_STATUS_TX_FULL) { + return 1; + } + + return 0; +} + +static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq) { + return proc_freq / (uart_freq * 16) - 1; +} + +void potato_uart_init(void) { + potato_uart_base = POTATO_UART_BASE; + potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ)); + +} + +char potato_uart_read(void) { + uint64_t val; + + while (potato_uart_rx_empty()); + val = potato_uart_reg_read(POTATO_CONSOLE_RX); + + return (char)(val & 0x000000ff); +} + +void potato_uart_write(char c) { + uint64_t val; + + val = c; + + while (potato_uart_tx_full()); + potato_uart_reg_write(POTATO_CONSOLE_TX, val); +} diff --git a/ports/powerpc/uart_potato.h b/ports/powerpc/uart_potato.h new file mode 100644 index 0000000000000..d6bd93aa4ea85 --- /dev/null +++ b/ports/powerpc/uart_potato.h @@ -0,0 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * 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. + */ + +void potato_uart_init(void); +char potato_uart_read(void); +void potato_uart_write(char c); diff --git a/ports/powerpc/unistd.h b/ports/powerpc/unistd.h new file mode 100644 index 0000000000000..88e3b27218ad6 --- /dev/null +++ b/ports/powerpc/unistd.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_POWERPC_UNISTD_H +#define MICROPY_INCLUDED_POWERPC_UNISTD_H + +// powerpc gcc compiler doesn't seem to have unistd.h file + +#define SEEK_SET 0 +#define SEEK_CUR 1 + +typedef int ssize_t; + +#endif // MICROPY_INCLUDED_POWERPC_UNISTD_H diff --git a/py/nlr.h b/py/nlr.h index f2453bc46008d..3be3eb58cc794 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -73,6 +73,10 @@ #elif defined(__xtensa__) #define MICROPY_NLR_XTENSA (1) #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_XTENSA) +#elif defined(__powerpc__) + #define MICROPY_NLR_POWERPC (1) + // this could be less but using 128 for safety + #define MICROPY_NLR_NUM_REGS (128) #else #define MICROPY_NLR_SETJMP (1) //#warning "No native NLR support for this arch, using setjmp implementation" diff --git a/py/nlrpowerpc.c b/py/nlrpowerpc.c new file mode 100644 index 0000000000000..b403823813e91 --- /dev/null +++ b/py/nlrpowerpc.c @@ -0,0 +1,121 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019, Michael Neuling, IBM Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpstate.h" + +#if MICROPY_NLR_POWERPC + +#undef nlr_push + +// Saving all ABI non-vol registers here + +unsigned int nlr_push(nlr_buf_t *nlr) { + + __asm__ volatile( + "li 4, 0x4eed ; " // Store canary + "std 4, 0x00(%0) ;" + "std 0, 0x08(%0) ;" + "std 1, 0x10(%0) ;" + "std 2, 0x18(%0) ;" + "std 14, 0x20(%0) ;" + "std 15, 0x28(%0) ;" + "std 16, 0x30(%0) ;" + "std 17, 0x38(%0) ;" + "std 18, 0x40(%0) ;" + "std 19, 0x48(%0) ;" + "std 20, 0x50(%0) ;" + "std 21, 0x58(%0) ;" + "std 22, 0x60(%0) ;" + "std 23, 0x68(%0) ;" + "std 24, 0x70(%0) ;" + "std 25, 0x78(%0) ;" + "std 26, 0x80(%0) ;" + "std 27, 0x88(%0) ;" + "std 28, 0x90(%0) ;" + "std 29, 0x98(%0) ;" + "std 30, 0xA0(%0) ;" + "std 31, 0xA8(%0) ;" + + "mfcr 4 ; " + "std 4, 0xB0(%0) ;" + "mflr 4 ;" + "std 4, 0xB8(%0) ;" + "li 4, nlr_push_tail@l ;" + "oris 4, 4, nlr_push_tail@h ;" + "mtctr 4 ;" + "mr 3, %1 ; " + "bctr ;" + : + : "r"(&nlr->regs), "r"(nlr) + : + ); + + return 0; +} + +NORETURN void nlr_jump(void *val) { + MP_NLR_JUMP_HEAD(val, top) + + __asm__ volatile( + "ld 3, 0x0(%0) ;" + "cmpdi 3, 0x4eed ; " // Check canary + "bne . ; " + "ld 0, 0x08(%0) ;" + "ld 1, 0x10(%0) ;" + "ld 2, 0x18(%0) ;" + "ld 14, 0x20(%0) ;" + "ld 15, 0x28(%0) ;" + "ld 16, 0x30(%0) ;" + "ld 17, 0x38(%0) ;" + "ld 18, 0x40(%0) ;" + "ld 19, 0x48(%0) ;" + "ld 20, 0x50(%0) ;" + "ld 21, 0x58(%0) ;" + "ld 22, 0x60(%0) ;" + "ld 23, 0x68(%0) ;" + "ld 24, 0x70(%0) ;" + "ld 25, 0x78(%0) ;" + "ld 26, 0x80(%0) ;" + "ld 27, 0x88(%0) ;" + "ld 28, 0x90(%0) ;" + "ld 29, 0x98(%0) ;" + "ld 30, 0xA0(%0) ;" + "ld 31, 0xA8(%0) ;" + "ld 3, 0xB0(%0) ;" + "mtcr 3 ;" + "ld 3, 0xB8(%0) ;" + "mtlr 3 ; " + "li 3, 1;" + "blr ;" + : + : "r"(&top->regs) + : + ); + + MP_UNREACHABLE; +} + +#endif // MICROPY_NLR_POWERPC diff --git a/py/py.mk b/py/py.mk index 514a0e405a8d6..d7021d32682f5 100644 --- a/py/py.mk +++ b/py/py.mk @@ -46,6 +46,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ nlrx86.o \ nlrx64.o \ nlrthumb.o \ + nlrpowerpc.o \ nlrxtensa.o \ nlrsetjmp.o \ malloc.o \ From f301170c7cb50fdb9250a6e4b89682f9c0e543cb Mon Sep 17 00:00:00 2001 From: Mike Teachman Date: Tue, 22 Oct 2019 10:25:37 -0700 Subject: [PATCH 0623/1299] esp32/machine_hw_spi: Fix exception msg when host is already in use. When a SPI bus is initialized with a SPI host that is currently in use the exception msg incorrectly indicates "SPI device already in use". The mention of "device" in the exception msg is confusing because the error is about trying to use a SPI host that is already claimed. A better exception msg is "SPI host already in use". --- ports/esp32/machine_hw_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c index 2f63a32d4a8cf..af47711aadbb8 100644 --- a/ports/esp32/machine_hw_spi.c +++ b/ports/esp32/machine_hw_spi.c @@ -205,7 +205,7 @@ STATIC void machine_hw_spi_init_internal( return; case ESP_ERR_INVALID_STATE: - mp_raise_msg(&mp_type_OSError, "SPI device already in use"); + mp_raise_msg(&mp_type_OSError, "SPI host already in use"); return; } From f69ef97f241434a1b3b6907336cf88cf4bb52780 Mon Sep 17 00:00:00 2001 From: Mike Wadsten Date: Wed, 23 Oct 2019 11:43:01 -0500 Subject: [PATCH 0624/1299] docs: Move ubluetooth under "MicroPython-specific libraries". CPython does not have a bluetooth module, so it is not appropriate to call ubluetooth a Python standard library or micro-library. --- docs/library/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/index.rst b/docs/library/index.rst index a2d11dee7f2f3..34b937d412216 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -80,7 +80,6 @@ it will fallback to loading the built-in ``ujson`` module. sys.rst uarray.rst ubinascii.rst - ubluetooth.rst ucollections.rst uerrno.rst uhashlib.rst @@ -112,6 +111,7 @@ the following libraries. machine.rst micropython.rst network.rst + ubluetooth.rst ucryptolib.rst uctypes.rst From ece4e21a55609163466d96875c60bb7f1556c468 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 28 Oct 2019 13:48:51 +1100 Subject: [PATCH 0625/1299] stm32/Makefile: Only enable hardware sqrt on parts that support it. Not enough to detect f7/h7, need to use the specific parts. Follow-up to 580a2656d10cc7c1fc93e094d7eb71f04d99c329. --- ports/stm32/Makefile | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 30d4d9b48fedc..fca92f841eddc 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -64,13 +64,18 @@ INC += -Ilwip_inc CFLAGS_CORTEX_M = -mthumb # Select hardware floating-point support +SUPPORTS_HARDWARE_FP_SINGLE = 0 +SUPPORTS_HARDWARE_FP_DOUBLE = 0 ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32F765xx STM32F767xx STM32F769xx STM32H743xx)) CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard +SUPPORTS_HARDWARE_FP_SINGLE = 1 +SUPPORTS_HARDWARE_FP_DOUBLE = 1 else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0)) CFLAGS_CORTEX_M += -msoft-float else CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard +SUPPORTS_HARDWARE_FP_SINGLE = 1 endif endif @@ -180,7 +185,7 @@ SRC_LIBM = $(addprefix lib/libm_dbl/,\ tgamma.c \ trunc.c \ ) -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f7 h7)) +ifeq ($(SUPPORTS_HARDWARE_FP_DOUBLE),1) SRC_LIBM += lib/libm_dbl/thumb_vfp_sqrt.c else SRC_LIBM += lib/libm_dbl/sqrt.c @@ -213,10 +218,10 @@ SRC_LIBM = $(addprefix lib/libm/,\ wf_lgamma.c \ wf_tgamma.c \ ) -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0)) -SRC_LIBM += lib/libm/ef_sqrt.c -else +ifeq ($(SUPPORTS_HARDWARE_FP_SINGLE),1) SRC_LIBM += lib/libm/thumb_vfp_sqrtf.c +else +SRC_LIBM += lib/libm/ef_sqrt.c endif endif From 9aabb6c01ba4166bb389e28b55f21614fca5aa7f Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 7 Sep 2019 14:03:41 +1000 Subject: [PATCH 0626/1299] extmod: Factor out block-device struct to make independent of fatfs. --- extmod/vfs.h | 20 +++++++++++++++++++ extmod/vfs_fat.c | 24 +++++++++++------------ extmod/vfs_fat.h | 19 +----------------- extmod/vfs_fat_diskio.c | 38 ++++++++++++++++++------------------ ports/cc3200/mods/pybflash.c | 18 ++++++++--------- ports/cc3200/mptask.c | 2 +- ports/nrf/main.c | 2 +- ports/stm32/main.c | 4 ++-- ports/stm32/sdcard.c | 18 ++++++++--------- ports/stm32/storage.c | 18 ++++++++--------- 10 files changed, 83 insertions(+), 80 deletions(-) diff --git a/extmod/vfs.h b/extmod/vfs.h index 730dea043113a..85b020faa5b94 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -38,6 +38,12 @@ #define MP_S_IFDIR (0x4000) #define MP_S_IFREG (0x8000) +// these are the values for mp_vfs_blockdev_t.flags +#define MP_BLOCKDEV_FLAG_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func +#define MP_BLOCKDEV_FLAG_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount +#define MP_BLOCKDEV_FLAG_HAVE_IOCTL (0x0004) // new protocol with ioctl +#define MP_BLOCKDEV_FLAG_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it + // constants for block protocol ioctl #define BP_IOCTL_INIT (1) #define BP_IOCTL_DEINIT (2) @@ -50,6 +56,20 @@ typedef struct _mp_vfs_proto_t { mp_import_stat_t (*import_stat)(void *self, const char *path); } mp_vfs_proto_t; +typedef struct _mp_vfs_blockdev_t { + uint16_t flags; + mp_obj_t readblocks[4]; + mp_obj_t writeblocks[4]; + // new protocol uses just ioctl, old uses sync (optional) and count + union { + mp_obj_t ioctl[4]; + struct { + mp_obj_t sync[2]; + mp_obj_t count[2]; + } old; + } u; +} mp_vfs_blockdev_t; + typedef struct _mp_vfs_mount_t { const char *str; // mount point with leading / size_t len; diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index ec7aaed388c69..dcfb677b1fad6 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -68,27 +68,27 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_ // create new object fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t); vfs->base.type = type; - vfs->flags = FSUSER_FREE_OBJ; + vfs->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; vfs->fatfs.drv = vfs; // load block protocol methods - mp_load_method(args[0], MP_QSTR_readblocks, vfs->readblocks); - mp_load_method_maybe(args[0], MP_QSTR_writeblocks, vfs->writeblocks); - mp_load_method_maybe(args[0], MP_QSTR_ioctl, vfs->u.ioctl); - if (vfs->u.ioctl[0] != MP_OBJ_NULL) { + mp_load_method(args[0], MP_QSTR_readblocks, vfs->blockdev.readblocks); + mp_load_method_maybe(args[0], MP_QSTR_writeblocks, vfs->blockdev.writeblocks); + mp_load_method_maybe(args[0], MP_QSTR_ioctl, vfs->blockdev.u.ioctl); + if (vfs->blockdev.u.ioctl[0] != MP_OBJ_NULL) { // device supports new block protocol, so indicate it - vfs->flags |= FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL; } else { // no ioctl method, so assume the device uses the old block protocol - mp_load_method_maybe(args[0], MP_QSTR_sync, vfs->u.old.sync); - mp_load_method(args[0], MP_QSTR_count, vfs->u.old.count); + mp_load_method_maybe(args[0], MP_QSTR_sync, vfs->blockdev.u.old.sync); + mp_load_method(args[0], MP_QSTR_count, vfs->blockdev.u.old.count); } // mount the block device so the VFS methods can be used FRESULT res = f_mount(&vfs->fatfs); if (res == FR_NO_FILESYSTEM) { // don't error out if no filesystem, to let mkfs()/mount() create one if wanted - vfs->flags |= FSUSER_NO_FILESYSTEM; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NO_FILESYSTEM; } else if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } @@ -380,11 +380,11 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs // 1. readonly=True keyword argument // 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already) if (mp_obj_is_true(readonly)) { - self->writeblocks[0] = MP_OBJ_NULL; + self->blockdev.writeblocks[0] = MP_OBJ_NULL; } // check if we need to make the filesystem - FRESULT res = (self->flags & FSUSER_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; + FRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) { uint8_t working_buf[FF_MAX_SS]; res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf)); @@ -392,7 +392,7 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } - self->flags &= ~FSUSER_NO_FILESYSTEM; + self->blockdev.flags &= ~MP_BLOCKDEV_FLAG_NO_FILESYSTEM; return mp_const_none; } diff --git a/extmod/vfs_fat.h b/extmod/vfs_fat.h index ba2915386fdb4..83685b5027b32 100644 --- a/extmod/vfs_fat.h +++ b/extmod/vfs_fat.h @@ -26,30 +26,13 @@ #ifndef MICROPY_INCLUDED_EXTMOD_VFS_FAT_H #define MICROPY_INCLUDED_EXTMOD_VFS_FAT_H -#include "py/lexer.h" #include "py/obj.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" -// these are the values for fs_user_mount_t.flags -#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func -#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount -#define FSUSER_HAVE_IOCTL (0x0004) // new protocol with ioctl -#define FSUSER_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it - typedef struct _fs_user_mount_t { mp_obj_base_t base; - uint16_t flags; - mp_obj_t readblocks[4]; - mp_obj_t writeblocks[4]; - // new protocol uses just ioctl, old uses sync (optional) and count - union { - mp_obj_t ioctl[4]; - struct { - mp_obj_t sync[2]; - mp_obj_t count[2]; - } old; - } u; + mp_vfs_blockdev_t blockdev; FATFS fatfs; } fs_user_mount_t; diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index e80d6124115f4..25b1310670cfd 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -69,16 +69,16 @@ DRESULT disk_read ( return RES_PARERR; } - if (vfs->flags & FSUSER_NATIVE) { - mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->readblocks[2]; + if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) { + mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.readblocks[2]; if (f(buff, sector, count) != 0) { return RES_ERROR; } } else { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), buff}; - vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->readblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, vfs->readblocks); + vfs->blockdev.readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); + vfs->blockdev.readblocks[3] = MP_OBJ_FROM_PTR(&ar); + mp_call_method_n_kw(2, 0, vfs->blockdev.readblocks); // TODO handle error return } @@ -101,21 +101,21 @@ DRESULT disk_write ( return RES_PARERR; } - if (vfs->writeblocks[0] == MP_OBJ_NULL) { + if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { // read-only block device return RES_WRPRT; } - if (vfs->flags & FSUSER_NATIVE) { - mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2]; + if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) { + mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.writeblocks[2]; if (f(buff, sector, count) != 0) { return RES_ERROR; } } else { mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), (void*)buff}; - vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, vfs->writeblocks); + vfs->blockdev.writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); + vfs->blockdev.writeblocks[3] = MP_OBJ_FROM_PTR(&ar); + mp_call_method_n_kw(2, 0, vfs->blockdev.writeblocks); // TODO handle error return } @@ -140,7 +140,7 @@ DRESULT disk_ioctl ( // First part: call the relevant method of the underlying block device mp_obj_t ret = mp_const_none; - if (vfs->flags & FSUSER_HAVE_IOCTL) { + if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) { // new protocol with ioctl static const uint8_t op_map[8] = { [CTRL_SYNC] = BP_IOCTL_SYNC, @@ -150,21 +150,21 @@ DRESULT disk_ioctl ( }; uint8_t bp_op = op_map[cmd & 7]; if (bp_op != 0) { - vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op); - vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused - ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl); + vfs->blockdev.u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op); + vfs->blockdev.u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused + ret = mp_call_method_n_kw(2, 0, vfs->blockdev.u.ioctl); } } else { // old protocol with sync and count switch (cmd) { case CTRL_SYNC: - if (vfs->u.old.sync[0] != MP_OBJ_NULL) { - mp_call_method_n_kw(0, 0, vfs->u.old.sync); + if (vfs->blockdev.u.old.sync[0] != MP_OBJ_NULL) { + mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.sync); } break; case GET_SECTOR_COUNT: - ret = mp_call_method_n_kw(0, 0, vfs->u.old.count); + ret = mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.count); break; case GET_SECTOR_SIZE: @@ -211,7 +211,7 @@ DRESULT disk_ioctl ( if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { // error initialising stat = STA_NOINIT; - } else if (vfs->writeblocks[0] == MP_OBJ_NULL) { + } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { stat = STA_PROTECT; } else { stat = 0; diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c index 51f4cb5172784..185913ce31fa7 100644 --- a/ports/cc3200/mods/pybflash.c +++ b/ports/cc3200/mods/pybflash.c @@ -96,14 +96,14 @@ const mp_obj_type_t pyb_flash_type = { void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; - vfs->readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&pyb_flash_obj; - vfs->readblocks[2] = (mp_obj_t)sflash_disk_read; // native version - vfs->writeblocks[0] = (mp_obj_t)&pyb_flash_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&pyb_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)sflash_disk_write; // native version - vfs->u.ioctl[0] = (mp_obj_t)&pyb_flash_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&pyb_flash_obj; + vfs->blockdev.readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj; + vfs->blockdev.readblocks[1] = (mp_obj_t)&pyb_flash_obj; + vfs->blockdev.readblocks[2] = (mp_obj_t)sflash_disk_read; // native version + vfs->blockdev.writeblocks[0] = (mp_obj_t)&pyb_flash_writeblocks_obj; + vfs->blockdev.writeblocks[1] = (mp_obj_t)&pyb_flash_obj; + vfs->blockdev.writeblocks[2] = (mp_obj_t)sflash_disk_write; // native version + vfs->blockdev.u.ioctl[0] = (mp_obj_t)&pyb_flash_ioctl_obj; + vfs->blockdev.u.ioctl[1] = (mp_obj_t)&pyb_flash_obj; } diff --git a/ports/cc3200/mptask.c b/ports/cc3200/mptask.c index d35338be18c9a..c253804267c5d 100644 --- a/ports/cc3200/mptask.c +++ b/ports/cc3200/mptask.c @@ -300,7 +300,7 @@ STATIC void mptask_init_sflash_filesystem (void) { // Initialise the local flash filesystem. // init the vfs object fs_user_mount_t *vfs_fat = sflash_vfs_fat; - vfs_fat->flags = 0; + vfs_fat->blockdev.flags = 0; pyb_flash_init_vfs(vfs_fat); // Create it if needed, and mount in on /flash. diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 26ac0ad6c9747..f7d42060e830e 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -180,7 +180,7 @@ pin_init0(); } vfs->str = "/sd"; vfs->len = 3; - vfs->flags = FSUSER_FREE_OBJ; + vfs->flags = MP_BLOCKDEV_FLAG_FREE_OBJ; sdcard_init_vfs(vfs); // put the sd device in slot 1 (it will be unused at this point) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 2da3626f1294b..685dbd10c7b1f 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -161,7 +161,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pyb_main_obj, 1, pyb_main); MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // init the vfs object fs_user_mount_t *vfs_fat = &fs_user_mount_flash; - vfs_fat->flags = 0; + vfs_fat->blockdev.flags = 0; pyb_flash_init_vfs(vfs_fat); // try to mount the flash @@ -230,7 +230,7 @@ STATIC bool init_sdcard_fs(void) { if (vfs == NULL || vfs_fat == NULL) { break; } - vfs_fat->flags = FSUSER_FREE_OBJ; + vfs_fat->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; sdcard_init_vfs(vfs_fat, part_num); // try to mount the partition diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 44b1c807d8e08..da9c1c681a887 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -873,17 +873,17 @@ const mp_obj_type_t pyb_mmcard_type = { void sdcard_init_vfs(fs_user_mount_t *vfs, int part) { pyb_sdmmc_flags = (pyb_sdmmc_flags & PYB_SDMMC_FLAG_ACTIVE) | PYB_SDMMC_FLAG_SD; // force SD mode vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; vfs->fatfs.part = part; - vfs->readblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_readblocks_obj); - vfs->readblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); - vfs->readblocks[2] = MP_OBJ_FROM_PTR(sdcard_read_blocks); // native version - vfs->writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_writeblocks_obj); - vfs->writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); - vfs->writeblocks[2] = MP_OBJ_FROM_PTR(sdcard_write_blocks); // native version - vfs->u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_ioctl_obj); - vfs->u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); + vfs->blockdev.readblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_readblocks_obj); + vfs->blockdev.readblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); + vfs->blockdev.readblocks[2] = MP_OBJ_FROM_PTR(sdcard_read_blocks); // native version + vfs->blockdev.writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_writeblocks_obj); + vfs->blockdev.writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); + vfs->blockdev.writeblocks[2] = MP_OBJ_FROM_PTR(sdcard_write_blocks); // native version + vfs->blockdev.u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_sdcard_ioctl_obj); + vfs->blockdev.u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_sdcard_obj); } #endif // MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index b150d73763612..7685f6f175b8c 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -290,17 +290,17 @@ const mp_obj_type_t pyb_flash_type = { void pyb_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; vfs->fatfs.drv = vfs; vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_readblocks_obj); - vfs->readblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); - vfs->readblocks[2] = MP_OBJ_FROM_PTR(storage_read_blocks); // native version - vfs->writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_writeblocks_obj); - vfs->writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); - vfs->writeblocks[2] = MP_OBJ_FROM_PTR(storage_write_blocks); // native version - vfs->u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_flash_ioctl_obj); - vfs->u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); + vfs->blockdev.readblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_readblocks_obj); + vfs->blockdev.readblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); + vfs->blockdev.readblocks[2] = MP_OBJ_FROM_PTR(storage_read_blocks); // native version + vfs->blockdev.writeblocks[0] = MP_OBJ_FROM_PTR(&pyb_flash_writeblocks_obj); + vfs->blockdev.writeblocks[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); + vfs->blockdev.writeblocks[2] = MP_OBJ_FROM_PTR(storage_write_blocks); // native version + vfs->blockdev.u.ioctl[0] = MP_OBJ_FROM_PTR(&pyb_flash_ioctl_obj); + vfs->blockdev.u.ioctl[1] = MP_OBJ_FROM_PTR(&pyb_flash_obj); } #endif From e1c7b1cb431f17bc00a76e7d411f5106b1a967cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 8 Sep 2019 22:01:09 +1000 Subject: [PATCH 0627/1299] extmod/vfs_blockdev: Factor out block device interface code. --- extmod/vfs.h | 6 +++ extmod/vfs_blockdev.c | 112 ++++++++++++++++++++++++++++++++++++++++ extmod/vfs_fat.c | 17 ++---- extmod/vfs_fat_diskio.c | 89 ++++++------------------------- py/py.mk | 1 + 5 files changed, 140 insertions(+), 85 deletions(-) create mode 100644 extmod/vfs_blockdev.c diff --git a/extmod/vfs.h b/extmod/vfs.h index 85b020faa5b94..e626a14df0cc5 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -58,6 +58,7 @@ typedef struct _mp_vfs_proto_t { typedef struct _mp_vfs_blockdev_t { uint16_t flags; + size_t block_size; mp_obj_t readblocks[4]; mp_obj_t writeblocks[4]; // new protocol uses just ioctl, old uses sync (optional) and count @@ -77,6 +78,11 @@ typedef struct _mp_vfs_mount_t { struct _mp_vfs_mount_t *next; } mp_vfs_mount_t; +void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev); +int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf); +int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf); +mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg); + mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out); mp_import_stat_t mp_vfs_import_stat(const char *path); mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); diff --git a/extmod/vfs_blockdev.c b/extmod/vfs_blockdev.c new file mode 100644 index 0000000000000..0bc0fdebfa211 --- /dev/null +++ b/extmod/vfs_blockdev.c @@ -0,0 +1,112 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/binary.h" +#include "py/objarray.h" +#include "py/mperrno.h" +#include "extmod/vfs.h" + +#if MICROPY_VFS + +void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) { + mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks); + mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks); + mp_load_method_maybe(bdev, MP_QSTR_ioctl, self->u.ioctl); + if (self->u.ioctl[0] != MP_OBJ_NULL) { + // Device supports new block protocol, so indicate it + self->flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL; + } else { + // No ioctl method, so assume the device uses the old block protocol + mp_load_method_maybe(bdev, MP_QSTR_sync, self->u.old.sync); + mp_load_method(bdev, MP_QSTR_count, self->u.old.count); + } +} + +int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) { + if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { + mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)self->readblocks[2]; + return f(buf, block_num, num_blocks); + } else { + mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks * self->block_size, buf}; + self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); + self->readblocks[3] = MP_OBJ_FROM_PTR(&ar); + mp_call_method_n_kw(2, 0, self->readblocks); + // TODO handle error return + return 0; + } +} + +int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) { + if (self->writeblocks[0] == MP_OBJ_NULL) { + // read-only block device + return -MP_EROFS; + } + + if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { + mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)self->writeblocks[2]; + return f(buf, block_num, num_blocks); + } else { + mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks * self->block_size, (void*)buf}; + self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); + self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); + mp_call_method_n_kw(2, 0, self->writeblocks); + // TODO handle error return + return 0; + } +} + +mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) { + if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) { + // New protocol with ioctl + self->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(cmd); + self->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(arg); + return mp_call_method_n_kw(2, 0, self->u.ioctl); + } else { + // Old protocol with sync and count + switch (cmd) { + case BP_IOCTL_SYNC: + if (self->u.old.sync[0] != MP_OBJ_NULL) { + mp_call_method_n_kw(0, 0, self->u.old.sync); + } + break; + + case BP_IOCTL_SEC_COUNT: + return mp_call_method_n_kw(0, 0, self->u.old.count); + + case BP_IOCTL_SEC_SIZE: + // Old protocol has fixed sector size of 512 bytes + break; + + case BP_IOCTL_INIT: + // Old protocol doesn't have init + break; + } + return mp_const_none; + } +} + +#endif // MICROPY_VFS diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index dcfb677b1fad6..129b6cc6695f0 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -68,21 +68,12 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_ // create new object fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t); vfs->base.type = type; - vfs->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; vfs->fatfs.drv = vfs; - // load block protocol methods - mp_load_method(args[0], MP_QSTR_readblocks, vfs->blockdev.readblocks); - mp_load_method_maybe(args[0], MP_QSTR_writeblocks, vfs->blockdev.writeblocks); - mp_load_method_maybe(args[0], MP_QSTR_ioctl, vfs->blockdev.u.ioctl); - if (vfs->blockdev.u.ioctl[0] != MP_OBJ_NULL) { - // device supports new block protocol, so indicate it - vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL; - } else { - // no ioctl method, so assume the device uses the old block protocol - mp_load_method_maybe(args[0], MP_QSTR_sync, vfs->blockdev.u.old.sync); - mp_load_method(args[0], MP_QSTR_count, vfs->blockdev.u.old.count); - } + // Initialise underlying block device + vfs->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; + vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to BP_IOCTL_SEC_SIZE + mp_vfs_blockdev_init(&vfs->blockdev, args[0]); // mount the block device so the VFS methods can be used FRESULT res = f_mount(&vfs->fatfs); diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index 25b1310670cfd..61a4d6da50e1f 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -38,16 +38,11 @@ #include "py/runtime.h" #include "py/binary.h" #include "py/objarray.h" +#include "py/mperrno.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs_fat.h" -#if FF_MAX_SS == FF_MIN_SS -#define SECSIZE(fs) (FF_MIN_SS) -#else -#define SECSIZE(fs) ((fs)->ssize) -#endif - typedef void *bdev_t; STATIC fs_user_mount_t *disk_get_device(void *bdev) { return (fs_user_mount_t*)bdev; @@ -69,20 +64,9 @@ DRESULT disk_read ( return RES_PARERR; } - if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) { - mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.readblocks[2]; - if (f(buff, sector, count) != 0) { - return RES_ERROR; - } - } else { - mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), buff}; - vfs->blockdev.readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->blockdev.readblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, vfs->blockdev.readblocks); - // TODO handle error return - } + int ret = mp_vfs_blockdev_read(&vfs->blockdev, sector, count, buff); - return RES_OK; + return ret == 0 ? RES_OK : RES_ERROR; } /*-----------------------------------------------------------------------*/ @@ -101,25 +85,14 @@ DRESULT disk_write ( return RES_PARERR; } - if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { + int ret = mp_vfs_blockdev_write(&vfs->blockdev, sector, count, buff); + + if (ret == -MP_EROFS) { // read-only block device return RES_WRPRT; } - if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) { - mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.writeblocks[2]; - if (f(buff, sector, count) != 0) { - return RES_ERROR; - } - } else { - mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), (void*)buff}; - vfs->blockdev.writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector); - vfs->blockdev.writeblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, vfs->blockdev.writeblocks); - // TODO handle error return - } - - return RES_OK; + return ret == 0 ? RES_OK : RES_ERROR; } @@ -139,42 +112,16 @@ DRESULT disk_ioctl ( } // First part: call the relevant method of the underlying block device + static const uint8_t op_map[8] = { + [CTRL_SYNC] = BP_IOCTL_SYNC, + [GET_SECTOR_COUNT] = BP_IOCTL_SEC_COUNT, + [GET_SECTOR_SIZE] = BP_IOCTL_SEC_SIZE, + [IOCTL_INIT] = BP_IOCTL_INIT, + }; + uint8_t bp_op = op_map[cmd & 7]; mp_obj_t ret = mp_const_none; - if (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) { - // new protocol with ioctl - static const uint8_t op_map[8] = { - [CTRL_SYNC] = BP_IOCTL_SYNC, - [GET_SECTOR_COUNT] = BP_IOCTL_SEC_COUNT, - [GET_SECTOR_SIZE] = BP_IOCTL_SEC_SIZE, - [IOCTL_INIT] = BP_IOCTL_INIT, - }; - uint8_t bp_op = op_map[cmd & 7]; - if (bp_op != 0) { - vfs->blockdev.u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op); - vfs->blockdev.u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused - ret = mp_call_method_n_kw(2, 0, vfs->blockdev.u.ioctl); - } - } else { - // old protocol with sync and count - switch (cmd) { - case CTRL_SYNC: - if (vfs->blockdev.u.old.sync[0] != MP_OBJ_NULL) { - mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.sync); - } - break; - - case GET_SECTOR_COUNT: - ret = mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.count); - break; - - case GET_SECTOR_SIZE: - // old protocol has fixed sector size of 512 bytes - break; - - case IOCTL_INIT: - // old protocol doesn't have init - break; - } + if (bp_op != 0) { + ret = mp_vfs_blockdev_ioctl(&vfs->blockdev, bp_op, 0); } // Second part: convert the result for return @@ -194,10 +141,8 @@ DRESULT disk_ioctl ( } else { *((WORD*)buff) = mp_obj_get_int(ret); } - #if FF_MAX_SS != FF_MIN_SS // need to store ssize because we use it in disk_read/disk_write - vfs->fatfs.ssize = *((WORD*)buff); - #endif + vfs->blockdev.block_size = *((WORD*)buff); return RES_OK; } diff --git a/py/py.mk b/py/py.mk index d7021d32682f5..b08b3f80c8418 100644 --- a/py/py.mk +++ b/py/py.mk @@ -185,6 +185,7 @@ PY_EXTMOD_O_BASENAME = \ extmod/modwebrepl.o \ extmod/modframebuf.o \ extmod/vfs.o \ + extmod/vfs_blockdev.o \ extmod/vfs_reader.o \ extmod/vfs_posix.o \ extmod/vfs_posix_file.o \ From 669d1d20ab8be16bc847d509a9397c2ad4f912fc Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 17:23:08 +1100 Subject: [PATCH 0628/1299] lib/littlefs: Add littlefs v1.7.2 source. --- lib/littlefs/lfs1.c | 2583 ++++++++++++++++++++++++++++++++++++++ lib/littlefs/lfs1.h | 501 ++++++++ lib/littlefs/lfs1_util.c | 31 + lib/littlefs/lfs1_util.h | 186 +++ 4 files changed, 3301 insertions(+) create mode 100644 lib/littlefs/lfs1.c create mode 100644 lib/littlefs/lfs1.h create mode 100644 lib/littlefs/lfs1_util.c create mode 100644 lib/littlefs/lfs1_util.h diff --git a/lib/littlefs/lfs1.c b/lib/littlefs/lfs1.c new file mode 100644 index 0000000000000..6a3fd670012cc --- /dev/null +++ b/lib/littlefs/lfs1.c @@ -0,0 +1,2583 @@ +/* + * The little filesystem + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "lfs1.h" +#include "lfs1_util.h" + +#include + + +/// Caching block device operations /// +static int lfs1_cache_read(lfs1_t *lfs1, lfs1_cache_t *rcache, + const lfs1_cache_t *pcache, lfs1_block_t block, + lfs1_off_t off, void *buffer, lfs1_size_t size) { + uint8_t *data = buffer; + LFS1_ASSERT(block < lfs1->cfg->block_count); + + while (size > 0) { + if (pcache && block == pcache->block && off >= pcache->off && + off < pcache->off + lfs1->cfg->prog_size) { + // is already in pcache? + lfs1_size_t diff = lfs1_min(size, + lfs1->cfg->prog_size - (off-pcache->off)); + memcpy(data, &pcache->buffer[off-pcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + if (block == rcache->block && off >= rcache->off && + off < rcache->off + lfs1->cfg->read_size) { + // is already in rcache? + lfs1_size_t diff = lfs1_min(size, + lfs1->cfg->read_size - (off-rcache->off)); + memcpy(data, &rcache->buffer[off-rcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + if (off % lfs1->cfg->read_size == 0 && size >= lfs1->cfg->read_size) { + // bypass cache? + lfs1_size_t diff = size - (size % lfs1->cfg->read_size); + int err = lfs1->cfg->read(lfs1->cfg, block, off, data, diff); + if (err) { + return err; + } + + data += diff; + off += diff; + size -= diff; + continue; + } + + // load to cache, first condition can no longer fail + rcache->block = block; + rcache->off = off - (off % lfs1->cfg->read_size); + int err = lfs1->cfg->read(lfs1->cfg, rcache->block, + rcache->off, rcache->buffer, lfs1->cfg->read_size); + if (err) { + return err; + } + } + + return 0; +} + +static int lfs1_cache_cmp(lfs1_t *lfs1, lfs1_cache_t *rcache, + const lfs1_cache_t *pcache, lfs1_block_t block, + lfs1_off_t off, const void *buffer, lfs1_size_t size) { + const uint8_t *data = buffer; + + for (lfs1_off_t i = 0; i < size; i++) { + uint8_t c; + int err = lfs1_cache_read(lfs1, rcache, pcache, + block, off+i, &c, 1); + if (err) { + return err; + } + + if (c != data[i]) { + return false; + } + } + + return true; +} + +static int lfs1_cache_crc(lfs1_t *lfs1, lfs1_cache_t *rcache, + const lfs1_cache_t *pcache, lfs1_block_t block, + lfs1_off_t off, lfs1_size_t size, uint32_t *crc) { + for (lfs1_off_t i = 0; i < size; i++) { + uint8_t c; + int err = lfs1_cache_read(lfs1, rcache, pcache, + block, off+i, &c, 1); + if (err) { + return err; + } + + lfs1_crc(crc, &c, 1); + } + + return 0; +} + +static inline void lfs1_cache_drop(lfs1_t *lfs1, lfs1_cache_t *rcache) { + // do not zero, cheaper if cache is readonly or only going to be + // written with identical data (during relocates) + (void)lfs1; + rcache->block = 0xffffffff; +} + +static inline void lfs1_cache_zero(lfs1_t *lfs1, lfs1_cache_t *pcache) { + // zero to avoid information leak + memset(pcache->buffer, 0xff, lfs1->cfg->prog_size); + pcache->block = 0xffffffff; +} + +static int lfs1_cache_flush(lfs1_t *lfs1, + lfs1_cache_t *pcache, lfs1_cache_t *rcache) { + if (pcache->block != 0xffffffff) { + int err = lfs1->cfg->prog(lfs1->cfg, pcache->block, + pcache->off, pcache->buffer, lfs1->cfg->prog_size); + if (err) { + return err; + } + + if (rcache) { + int res = lfs1_cache_cmp(lfs1, rcache, NULL, pcache->block, + pcache->off, pcache->buffer, lfs1->cfg->prog_size); + if (res < 0) { + return res; + } + + if (!res) { + return LFS1_ERR_CORRUPT; + } + } + + lfs1_cache_zero(lfs1, pcache); + } + + return 0; +} + +static int lfs1_cache_prog(lfs1_t *lfs1, lfs1_cache_t *pcache, + lfs1_cache_t *rcache, lfs1_block_t block, + lfs1_off_t off, const void *buffer, lfs1_size_t size) { + const uint8_t *data = buffer; + LFS1_ASSERT(block < lfs1->cfg->block_count); + + while (size > 0) { + if (block == pcache->block && off >= pcache->off && + off < pcache->off + lfs1->cfg->prog_size) { + // is already in pcache? + lfs1_size_t diff = lfs1_min(size, + lfs1->cfg->prog_size - (off-pcache->off)); + memcpy(&pcache->buffer[off-pcache->off], data, diff); + + data += diff; + off += diff; + size -= diff; + + if (off % lfs1->cfg->prog_size == 0) { + // eagerly flush out pcache if we fill up + int err = lfs1_cache_flush(lfs1, pcache, rcache); + if (err) { + return err; + } + } + + continue; + } + + // pcache must have been flushed, either by programming and + // entire block or manually flushing the pcache + LFS1_ASSERT(pcache->block == 0xffffffff); + + if (off % lfs1->cfg->prog_size == 0 && + size >= lfs1->cfg->prog_size) { + // bypass pcache? + lfs1_size_t diff = size - (size % lfs1->cfg->prog_size); + int err = lfs1->cfg->prog(lfs1->cfg, block, off, data, diff); + if (err) { + return err; + } + + if (rcache) { + int res = lfs1_cache_cmp(lfs1, rcache, NULL, + block, off, data, diff); + if (res < 0) { + return res; + } + + if (!res) { + return LFS1_ERR_CORRUPT; + } + } + + data += diff; + off += diff; + size -= diff; + continue; + } + + // prepare pcache, first condition can no longer fail + pcache->block = block; + pcache->off = off - (off % lfs1->cfg->prog_size); + } + + return 0; +} + + +/// General lfs1 block device operations /// +static int lfs1_bd_read(lfs1_t *lfs1, lfs1_block_t block, + lfs1_off_t off, void *buffer, lfs1_size_t size) { + // if we ever do more than writes to alternating pairs, + // this may need to consider pcache + return lfs1_cache_read(lfs1, &lfs1->rcache, NULL, + block, off, buffer, size); +} + +static int lfs1_bd_prog(lfs1_t *lfs1, lfs1_block_t block, + lfs1_off_t off, const void *buffer, lfs1_size_t size) { + return lfs1_cache_prog(lfs1, &lfs1->pcache, NULL, + block, off, buffer, size); +} + +static int lfs1_bd_cmp(lfs1_t *lfs1, lfs1_block_t block, + lfs1_off_t off, const void *buffer, lfs1_size_t size) { + return lfs1_cache_cmp(lfs1, &lfs1->rcache, NULL, block, off, buffer, size); +} + +static int lfs1_bd_crc(lfs1_t *lfs1, lfs1_block_t block, + lfs1_off_t off, lfs1_size_t size, uint32_t *crc) { + return lfs1_cache_crc(lfs1, &lfs1->rcache, NULL, block, off, size, crc); +} + +static int lfs1_bd_erase(lfs1_t *lfs1, lfs1_block_t block) { + return lfs1->cfg->erase(lfs1->cfg, block); +} + +static int lfs1_bd_sync(lfs1_t *lfs1) { + lfs1_cache_drop(lfs1, &lfs1->rcache); + + int err = lfs1_cache_flush(lfs1, &lfs1->pcache, NULL); + if (err) { + return err; + } + + return lfs1->cfg->sync(lfs1->cfg); +} + + +/// Internal operations predeclared here /// +int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data); +static int lfs1_pred(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *pdir); +static int lfs1_parent(lfs1_t *lfs1, const lfs1_block_t dir[2], + lfs1_dir_t *parent, lfs1_entry_t *entry); +static int lfs1_moved(lfs1_t *lfs1, const void *e); +static int lfs1_relocate(lfs1_t *lfs1, + const lfs1_block_t oldpair[2], const lfs1_block_t newpair[2]); +int lfs1_deorphan(lfs1_t *lfs1); + + +/// Block allocator /// +static int lfs1_alloc_lookahead(void *p, lfs1_block_t block) { + lfs1_t *lfs1 = p; + + lfs1_block_t off = ((block - lfs1->free.off) + + lfs1->cfg->block_count) % lfs1->cfg->block_count; + + if (off < lfs1->free.size) { + lfs1->free.buffer[off / 32] |= 1U << (off % 32); + } + + return 0; +} + +static int lfs1_alloc(lfs1_t *lfs1, lfs1_block_t *block) { + while (true) { + while (lfs1->free.i != lfs1->free.size) { + lfs1_block_t off = lfs1->free.i; + lfs1->free.i += 1; + lfs1->free.ack -= 1; + + if (!(lfs1->free.buffer[off / 32] & (1U << (off % 32)))) { + // found a free block + *block = (lfs1->free.off + off) % lfs1->cfg->block_count; + + // eagerly find next off so an alloc ack can + // discredit old lookahead blocks + while (lfs1->free.i != lfs1->free.size && + (lfs1->free.buffer[lfs1->free.i / 32] + & (1U << (lfs1->free.i % 32)))) { + lfs1->free.i += 1; + lfs1->free.ack -= 1; + } + + return 0; + } + } + + // check if we have looked at all blocks since last ack + if (lfs1->free.ack == 0) { + LFS1_WARN("No more free space %" PRIu32, + lfs1->free.i + lfs1->free.off); + return LFS1_ERR_NOSPC; + } + + lfs1->free.off = (lfs1->free.off + lfs1->free.size) + % lfs1->cfg->block_count; + lfs1->free.size = lfs1_min(lfs1->cfg->lookahead, lfs1->free.ack); + lfs1->free.i = 0; + + // find mask of free blocks from tree + memset(lfs1->free.buffer, 0, lfs1->cfg->lookahead/8); + int err = lfs1_traverse(lfs1, lfs1_alloc_lookahead, lfs1); + if (err) { + return err; + } + } +} + +static void lfs1_alloc_ack(lfs1_t *lfs1) { + lfs1->free.ack = lfs1->cfg->block_count; +} + + +/// Endian swapping functions /// +static void lfs1_dir_fromle32(struct lfs1_disk_dir *d) { + d->rev = lfs1_fromle32(d->rev); + d->size = lfs1_fromle32(d->size); + d->tail[0] = lfs1_fromle32(d->tail[0]); + d->tail[1] = lfs1_fromle32(d->tail[1]); +} + +static void lfs1_dir_tole32(struct lfs1_disk_dir *d) { + d->rev = lfs1_tole32(d->rev); + d->size = lfs1_tole32(d->size); + d->tail[0] = lfs1_tole32(d->tail[0]); + d->tail[1] = lfs1_tole32(d->tail[1]); +} + +static void lfs1_entry_fromle32(struct lfs1_disk_entry *d) { + d->u.dir[0] = lfs1_fromle32(d->u.dir[0]); + d->u.dir[1] = lfs1_fromle32(d->u.dir[1]); +} + +static void lfs1_entry_tole32(struct lfs1_disk_entry *d) { + d->u.dir[0] = lfs1_tole32(d->u.dir[0]); + d->u.dir[1] = lfs1_tole32(d->u.dir[1]); +} + +static void lfs1_superblock_fromle32(struct lfs1_disk_superblock *d) { + d->root[0] = lfs1_fromle32(d->root[0]); + d->root[1] = lfs1_fromle32(d->root[1]); + d->block_size = lfs1_fromle32(d->block_size); + d->block_count = lfs1_fromle32(d->block_count); + d->version = lfs1_fromle32(d->version); +} + +static void lfs1_superblock_tole32(struct lfs1_disk_superblock *d) { + d->root[0] = lfs1_tole32(d->root[0]); + d->root[1] = lfs1_tole32(d->root[1]); + d->block_size = lfs1_tole32(d->block_size); + d->block_count = lfs1_tole32(d->block_count); + d->version = lfs1_tole32(d->version); +} + + +/// Metadata pair and directory operations /// +static inline void lfs1_pairswap(lfs1_block_t pair[2]) { + lfs1_block_t t = pair[0]; + pair[0] = pair[1]; + pair[1] = t; +} + +static inline bool lfs1_pairisnull(const lfs1_block_t pair[2]) { + return pair[0] == 0xffffffff || pair[1] == 0xffffffff; +} + +static inline int lfs1_paircmp( + const lfs1_block_t paira[2], + const lfs1_block_t pairb[2]) { + return !(paira[0] == pairb[0] || paira[1] == pairb[1] || + paira[0] == pairb[1] || paira[1] == pairb[0]); +} + +static inline bool lfs1_pairsync( + const lfs1_block_t paira[2], + const lfs1_block_t pairb[2]) { + return (paira[0] == pairb[0] && paira[1] == pairb[1]) || + (paira[0] == pairb[1] && paira[1] == pairb[0]); +} + +static inline lfs1_size_t lfs1_entry_size(const lfs1_entry_t *entry) { + return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; +} + +static int lfs1_dir_alloc(lfs1_t *lfs1, lfs1_dir_t *dir) { + // allocate pair of dir blocks + for (int i = 0; i < 2; i++) { + int err = lfs1_alloc(lfs1, &dir->pair[i]); + if (err) { + return err; + } + } + + // rather than clobbering one of the blocks we just pretend + // the revision may be valid + int err = lfs1_bd_read(lfs1, dir->pair[0], 0, &dir->d.rev, 4); + if (err && err != LFS1_ERR_CORRUPT) { + return err; + } + + if (err != LFS1_ERR_CORRUPT) { + dir->d.rev = lfs1_fromle32(dir->d.rev); + } + + // set defaults + dir->d.rev += 1; + dir->d.size = sizeof(dir->d)+4; + dir->d.tail[0] = 0xffffffff; + dir->d.tail[1] = 0xffffffff; + dir->off = sizeof(dir->d); + + // don't write out yet, let caller take care of that + return 0; +} + +static int lfs1_dir_fetch(lfs1_t *lfs1, + lfs1_dir_t *dir, const lfs1_block_t pair[2]) { + // copy out pair, otherwise may be aliasing dir + const lfs1_block_t tpair[2] = {pair[0], pair[1]}; + bool valid = false; + + // check both blocks for the most recent revision + for (int i = 0; i < 2; i++) { + struct lfs1_disk_dir test; + int err = lfs1_bd_read(lfs1, tpair[i], 0, &test, sizeof(test)); + lfs1_dir_fromle32(&test); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + continue; + } + return err; + } + + if (valid && lfs1_scmp(test.rev, dir->d.rev) < 0) { + continue; + } + + if ((0x7fffffff & test.size) < sizeof(test)+4 || + (0x7fffffff & test.size) > lfs1->cfg->block_size) { + continue; + } + + uint32_t crc = 0xffffffff; + lfs1_dir_tole32(&test); + lfs1_crc(&crc, &test, sizeof(test)); + lfs1_dir_fromle32(&test); + err = lfs1_bd_crc(lfs1, tpair[i], sizeof(test), + (0x7fffffff & test.size) - sizeof(test), &crc); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + continue; + } + return err; + } + + if (crc != 0) { + continue; + } + + valid = true; + + // setup dir in case it's valid + dir->pair[0] = tpair[(i+0) % 2]; + dir->pair[1] = tpair[(i+1) % 2]; + dir->off = sizeof(dir->d); + dir->d = test; + } + + if (!valid) { + LFS1_ERROR("Corrupted dir pair at %" PRIu32 " %" PRIu32 , + tpair[0], tpair[1]); + return LFS1_ERR_CORRUPT; + } + + return 0; +} + +struct lfs1_region { + lfs1_off_t oldoff; + lfs1_size_t oldlen; + const void *newdata; + lfs1_size_t newlen; +}; + +static int lfs1_dir_commit(lfs1_t *lfs1, lfs1_dir_t *dir, + const struct lfs1_region *regions, int count) { + // increment revision count + dir->d.rev += 1; + + // keep pairs in order such that pair[0] is most recent + lfs1_pairswap(dir->pair); + for (int i = 0; i < count; i++) { + dir->d.size += regions[i].newlen - regions[i].oldlen; + } + + const lfs1_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; + bool relocated = false; + + while (true) { + if (true) { + int err = lfs1_bd_erase(lfs1, dir->pair[0]); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + uint32_t crc = 0xffffffff; + lfs1_dir_tole32(&dir->d); + lfs1_crc(&crc, &dir->d, sizeof(dir->d)); + err = lfs1_bd_prog(lfs1, dir->pair[0], 0, &dir->d, sizeof(dir->d)); + lfs1_dir_fromle32(&dir->d); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + int i = 0; + lfs1_off_t oldoff = sizeof(dir->d); + lfs1_off_t newoff = sizeof(dir->d); + while (newoff < (0x7fffffff & dir->d.size)-4) { + if (i < count && regions[i].oldoff == oldoff) { + lfs1_crc(&crc, regions[i].newdata, regions[i].newlen); + err = lfs1_bd_prog(lfs1, dir->pair[0], + newoff, regions[i].newdata, regions[i].newlen); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + oldoff += regions[i].oldlen; + newoff += regions[i].newlen; + i += 1; + } else { + uint8_t data; + err = lfs1_bd_read(lfs1, oldpair[1], oldoff, &data, 1); + if (err) { + return err; + } + + lfs1_crc(&crc, &data, 1); + err = lfs1_bd_prog(lfs1, dir->pair[0], newoff, &data, 1); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + oldoff += 1; + newoff += 1; + } + } + + crc = lfs1_tole32(crc); + err = lfs1_bd_prog(lfs1, dir->pair[0], newoff, &crc, 4); + crc = lfs1_fromle32(crc); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + err = lfs1_bd_sync(lfs1); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // successful commit, check checksum to make sure + uint32_t ncrc = 0xffffffff; + err = lfs1_bd_crc(lfs1, dir->pair[0], 0, + (0x7fffffff & dir->d.size)-4, &ncrc); + if (err) { + return err; + } + + if (ncrc != crc) { + goto relocate; + } + } + + break; +relocate: + //commit was corrupted + LFS1_DEBUG("Bad block at %" PRIu32, dir->pair[0]); + + // drop caches and prepare to relocate block + relocated = true; + lfs1_cache_drop(lfs1, &lfs1->pcache); + + // can't relocate superblock, filesystem is now frozen + if (lfs1_paircmp(oldpair, (const lfs1_block_t[2]){0, 1}) == 0) { + LFS1_WARN("Superblock %" PRIu32 " has become unwritable", + oldpair[0]); + return LFS1_ERR_CORRUPT; + } + + // relocate half of pair + int err = lfs1_alloc(lfs1, &dir->pair[0]); + if (err) { + return err; + } + } + + if (relocated) { + // update references if we relocated + LFS1_DEBUG("Relocating %" PRIu32 " %" PRIu32 " to %" PRIu32 " %" PRIu32, + oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); + int err = lfs1_relocate(lfs1, oldpair, dir->pair); + if (err) { + return err; + } + } + + // shift over any directories that are affected + for (lfs1_dir_t *d = lfs1->dirs; d; d = d->next) { + if (lfs1_paircmp(d->pair, dir->pair) == 0) { + d->pair[0] = dir->pair[0]; + d->pair[1] = dir->pair[1]; + } + } + + return 0; +} + +static int lfs1_dir_update(lfs1_t *lfs1, lfs1_dir_t *dir, + lfs1_entry_t *entry, const void *data) { + lfs1_entry_tole32(&entry->d); + int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ + {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, + {entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen} + }, data ? 2 : 1); + lfs1_entry_fromle32(&entry->d); + return err; +} + +static int lfs1_dir_append(lfs1_t *lfs1, lfs1_dir_t *dir, + lfs1_entry_t *entry, const void *data) { + // check if we fit, if top bit is set we do not and move on + while (true) { + if (dir->d.size + lfs1_entry_size(entry) <= lfs1->cfg->block_size) { + entry->off = dir->d.size - 4; + + lfs1_entry_tole32(&entry->d); + int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ + {entry->off, 0, &entry->d, sizeof(entry->d)}, + {entry->off, 0, data, entry->d.nlen} + }, 2); + lfs1_entry_fromle32(&entry->d); + return err; + } + + // we need to allocate a new dir block + if (!(0x80000000 & dir->d.size)) { + lfs1_dir_t olddir = *dir; + int err = lfs1_dir_alloc(lfs1, dir); + if (err) { + return err; + } + + dir->d.tail[0] = olddir.d.tail[0]; + dir->d.tail[1] = olddir.d.tail[1]; + entry->off = dir->d.size - 4; + lfs1_entry_tole32(&entry->d); + err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ + {entry->off, 0, &entry->d, sizeof(entry->d)}, + {entry->off, 0, data, entry->d.nlen} + }, 2); + lfs1_entry_fromle32(&entry->d); + if (err) { + return err; + } + + olddir.d.size |= 0x80000000; + olddir.d.tail[0] = dir->pair[0]; + olddir.d.tail[1] = dir->pair[1]; + return lfs1_dir_commit(lfs1, &olddir, NULL, 0); + } + + int err = lfs1_dir_fetch(lfs1, dir, dir->d.tail); + if (err) { + return err; + } + } +} + +static int lfs1_dir_remove(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry) { + // check if we should just drop the directory block + if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + + lfs1_entry_size(entry)) { + lfs1_dir_t pdir; + int res = lfs1_pred(lfs1, dir->pair, &pdir); + if (res < 0) { + return res; + } + + if (pdir.d.size & 0x80000000) { + pdir.d.size &= dir->d.size | 0x7fffffff; + pdir.d.tail[0] = dir->d.tail[0]; + pdir.d.tail[1] = dir->d.tail[1]; + return lfs1_dir_commit(lfs1, &pdir, NULL, 0); + } + } + + // shift out the entry + int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){ + {entry->off, lfs1_entry_size(entry), NULL, 0}, + }, 1); + if (err) { + return err; + } + + // shift over any files/directories that are affected + for (lfs1_file_t *f = lfs1->files; f; f = f->next) { + if (lfs1_paircmp(f->pair, dir->pair) == 0) { + if (f->poff == entry->off) { + f->pair[0] = 0xffffffff; + f->pair[1] = 0xffffffff; + } else if (f->poff > entry->off) { + f->poff -= lfs1_entry_size(entry); + } + } + } + + for (lfs1_dir_t *d = lfs1->dirs; d; d = d->next) { + if (lfs1_paircmp(d->pair, dir->pair) == 0) { + if (d->off > entry->off) { + d->off -= lfs1_entry_size(entry); + d->pos -= lfs1_entry_size(entry); + } + } + } + + return 0; +} + +static int lfs1_dir_next(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry) { + while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) { + if (!(0x80000000 & dir->d.size)) { + entry->off = dir->off; + return LFS1_ERR_NOENT; + } + + int err = lfs1_dir_fetch(lfs1, dir, dir->d.tail); + if (err) { + return err; + } + + dir->off = sizeof(dir->d); + dir->pos += sizeof(dir->d) + 4; + } + + int err = lfs1_bd_read(lfs1, dir->pair[0], dir->off, + &entry->d, sizeof(entry->d)); + lfs1_entry_fromle32(&entry->d); + if (err) { + return err; + } + + entry->off = dir->off; + dir->off += lfs1_entry_size(entry); + dir->pos += lfs1_entry_size(entry); + return 0; +} + +static int lfs1_dir_find(lfs1_t *lfs1, lfs1_dir_t *dir, + lfs1_entry_t *entry, const char **path) { + const char *pathname = *path; + size_t pathlen; + entry->d.type = LFS1_TYPE_DIR; + entry->d.elen = sizeof(entry->d) - 4; + entry->d.alen = 0; + entry->d.nlen = 0; + entry->d.u.dir[0] = lfs1->root[0]; + entry->d.u.dir[1] = lfs1->root[1]; + + while (true) { +nextname: + // skip slashes + pathname += strspn(pathname, "/"); + pathlen = strcspn(pathname, "/"); + + // skip '.' and root '..' + if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || + (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { + pathname += pathlen; + goto nextname; + } + + // skip if matched by '..' in name + const char *suffix = pathname + pathlen; + size_t sufflen; + int depth = 1; + while (true) { + suffix += strspn(suffix, "/"); + sufflen = strcspn(suffix, "/"); + if (sufflen == 0) { + break; + } + + if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { + depth -= 1; + if (depth == 0) { + pathname = suffix + sufflen; + goto nextname; + } + } else { + depth += 1; + } + + suffix += sufflen; + } + + // found path + if (pathname[0] == '\0') { + return 0; + } + + // update what we've found + *path = pathname; + + // continue on if we hit a directory + if (entry->d.type != LFS1_TYPE_DIR) { + return LFS1_ERR_NOTDIR; + } + + int err = lfs1_dir_fetch(lfs1, dir, entry->d.u.dir); + if (err) { + return err; + } + + // find entry matching name + while (true) { + err = lfs1_dir_next(lfs1, dir, entry); + if (err) { + return err; + } + + if (((0x7f & entry->d.type) != LFS1_TYPE_REG && + (0x7f & entry->d.type) != LFS1_TYPE_DIR) || + entry->d.nlen != pathlen) { + continue; + } + + int res = lfs1_bd_cmp(lfs1, dir->pair[0], + entry->off + 4+entry->d.elen+entry->d.alen, + pathname, pathlen); + if (res < 0) { + return res; + } + + // found match + if (res) { + break; + } + } + + // check that entry has not been moved + if (!lfs1->moving && entry->d.type & 0x80) { + int moved = lfs1_moved(lfs1, &entry->d.u); + if (moved < 0 || moved) { + return (moved < 0) ? moved : LFS1_ERR_NOENT; + } + + entry->d.type &= ~0x80; + } + + // to next name + pathname += pathlen; + } +} + + +/// Top level directory operations /// +int lfs1_mkdir(lfs1_t *lfs1, const char *path) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs1->deorphaned) { + int err = lfs1_deorphan(lfs1); + if (err) { + return err; + } + } + + // fetch parent directory + lfs1_dir_t cwd; + lfs1_entry_t entry; + int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); + if (err != LFS1_ERR_NOENT || strchr(path, '/') != NULL) { + return err ? err : LFS1_ERR_EXIST; + } + + // build up new directory + lfs1_alloc_ack(lfs1); + + lfs1_dir_t dir; + err = lfs1_dir_alloc(lfs1, &dir); + if (err) { + return err; + } + dir.d.tail[0] = cwd.d.tail[0]; + dir.d.tail[1] = cwd.d.tail[1]; + + err = lfs1_dir_commit(lfs1, &dir, NULL, 0); + if (err) { + return err; + } + + entry.d.type = LFS1_TYPE_DIR; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = 0; + entry.d.nlen = strlen(path); + entry.d.u.dir[0] = dir.pair[0]; + entry.d.u.dir[1] = dir.pair[1]; + + cwd.d.tail[0] = dir.pair[0]; + cwd.d.tail[1] = dir.pair[1]; + + err = lfs1_dir_append(lfs1, &cwd, &entry, path); + if (err) { + return err; + } + + lfs1_alloc_ack(lfs1); + return 0; +} + +int lfs1_dir_open(lfs1_t *lfs1, lfs1_dir_t *dir, const char *path) { + dir->pair[0] = lfs1->root[0]; + dir->pair[1] = lfs1->root[1]; + + lfs1_entry_t entry; + int err = lfs1_dir_find(lfs1, dir, &entry, &path); + if (err) { + return err; + } else if (entry.d.type != LFS1_TYPE_DIR) { + return LFS1_ERR_NOTDIR; + } + + err = lfs1_dir_fetch(lfs1, dir, entry.d.u.dir); + if (err) { + return err; + } + + // setup head dir + // special offset for '.' and '..' + dir->head[0] = dir->pair[0]; + dir->head[1] = dir->pair[1]; + dir->pos = sizeof(dir->d) - 2; + dir->off = sizeof(dir->d); + + // add to list of directories + dir->next = lfs1->dirs; + lfs1->dirs = dir; + + return 0; +} + +int lfs1_dir_close(lfs1_t *lfs1, lfs1_dir_t *dir) { + // remove from list of directories + for (lfs1_dir_t **p = &lfs1->dirs; *p; p = &(*p)->next) { + if (*p == dir) { + *p = dir->next; + break; + } + } + + return 0; +} + +int lfs1_dir_read(lfs1_t *lfs1, lfs1_dir_t *dir, struct lfs1_info *info) { + memset(info, 0, sizeof(*info)); + + // special offset for '.' and '..' + if (dir->pos == sizeof(dir->d) - 2) { + info->type = LFS1_TYPE_DIR; + strcpy(info->name, "."); + dir->pos += 1; + return 1; + } else if (dir->pos == sizeof(dir->d) - 1) { + info->type = LFS1_TYPE_DIR; + strcpy(info->name, ".."); + dir->pos += 1; + return 1; + } + + lfs1_entry_t entry; + while (true) { + int err = lfs1_dir_next(lfs1, dir, &entry); + if (err) { + return (err == LFS1_ERR_NOENT) ? 0 : err; + } + + if ((0x7f & entry.d.type) != LFS1_TYPE_REG && + (0x7f & entry.d.type) != LFS1_TYPE_DIR) { + continue; + } + + // check that entry has not been moved + if (entry.d.type & 0x80) { + int moved = lfs1_moved(lfs1, &entry.d.u); + if (moved < 0) { + return moved; + } + + if (moved) { + continue; + } + + entry.d.type &= ~0x80; + } + + break; + } + + info->type = entry.d.type; + if (info->type == LFS1_TYPE_REG) { + info->size = entry.d.u.file.size; + } + + int err = lfs1_bd_read(lfs1, dir->pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); + if (err) { + return err; + } + + return 1; +} + +int lfs1_dir_seek(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_off_t off) { + // simply walk from head dir + int err = lfs1_dir_rewind(lfs1, dir); + if (err) { + return err; + } + dir->pos = off; + + while (off > (0x7fffffff & dir->d.size)) { + off -= 0x7fffffff & dir->d.size; + if (!(0x80000000 & dir->d.size)) { + return LFS1_ERR_INVAL; + } + + err = lfs1_dir_fetch(lfs1, dir, dir->d.tail); + if (err) { + return err; + } + } + + dir->off = off; + return 0; +} + +lfs1_soff_t lfs1_dir_tell(lfs1_t *lfs1, lfs1_dir_t *dir) { + (void)lfs1; + return dir->pos; +} + +int lfs1_dir_rewind(lfs1_t *lfs1, lfs1_dir_t *dir) { + // reload the head dir + int err = lfs1_dir_fetch(lfs1, dir, dir->head); + if (err) { + return err; + } + + dir->pair[0] = dir->head[0]; + dir->pair[1] = dir->head[1]; + dir->pos = sizeof(dir->d) - 2; + dir->off = sizeof(dir->d); + return 0; +} + + +/// File index list operations /// +static int lfs1_ctz_index(lfs1_t *lfs1, lfs1_off_t *off) { + lfs1_off_t size = *off; + lfs1_off_t b = lfs1->cfg->block_size - 2*4; + lfs1_off_t i = size / b; + if (i == 0) { + return 0; + } + + i = (size - 4*(lfs1_popc(i-1)+2)) / b; + *off = size - b*i - 4*lfs1_popc(i); + return i; +} + +static int lfs1_ctz_find(lfs1_t *lfs1, + lfs1_cache_t *rcache, const lfs1_cache_t *pcache, + lfs1_block_t head, lfs1_size_t size, + lfs1_size_t pos, lfs1_block_t *block, lfs1_off_t *off) { + if (size == 0) { + *block = 0xffffffff; + *off = 0; + return 0; + } + + lfs1_off_t current = lfs1_ctz_index(lfs1, &(lfs1_off_t){size-1}); + lfs1_off_t target = lfs1_ctz_index(lfs1, &pos); + + while (current > target) { + lfs1_size_t skip = lfs1_min( + lfs1_npw2(current-target+1) - 1, + lfs1_ctz(current)); + + int err = lfs1_cache_read(lfs1, rcache, pcache, head, 4*skip, &head, 4); + head = lfs1_fromle32(head); + if (err) { + return err; + } + + LFS1_ASSERT(head >= 2 && head <= lfs1->cfg->block_count); + current -= 1 << skip; + } + + *block = head; + *off = pos; + return 0; +} + +static int lfs1_ctz_extend(lfs1_t *lfs1, + lfs1_cache_t *rcache, lfs1_cache_t *pcache, + lfs1_block_t head, lfs1_size_t size, + lfs1_block_t *block, lfs1_off_t *off) { + while (true) { + // go ahead and grab a block + lfs1_block_t nblock; + int err = lfs1_alloc(lfs1, &nblock); + if (err) { + return err; + } + LFS1_ASSERT(nblock >= 2 && nblock <= lfs1->cfg->block_count); + + if (true) { + err = lfs1_bd_erase(lfs1, nblock); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (size == 0) { + *block = nblock; + *off = 0; + return 0; + } + + size -= 1; + lfs1_off_t index = lfs1_ctz_index(lfs1, &size); + size += 1; + + // just copy out the last block if it is incomplete + if (size != lfs1->cfg->block_size) { + for (lfs1_off_t i = 0; i < size; i++) { + uint8_t data; + err = lfs1_cache_read(lfs1, rcache, NULL, + head, i, &data, 1); + if (err) { + return err; + } + + err = lfs1_cache_prog(lfs1, pcache, rcache, + nblock, i, &data, 1); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + *block = nblock; + *off = size; + return 0; + } + + // append block + index += 1; + lfs1_size_t skips = lfs1_ctz(index) + 1; + + for (lfs1_off_t i = 0; i < skips; i++) { + head = lfs1_tole32(head); + err = lfs1_cache_prog(lfs1, pcache, rcache, + nblock, 4*i, &head, 4); + head = lfs1_fromle32(head); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (i != skips-1) { + err = lfs1_cache_read(lfs1, rcache, NULL, + head, 4*i, &head, 4); + head = lfs1_fromle32(head); + if (err) { + return err; + } + } + + LFS1_ASSERT(head >= 2 && head <= lfs1->cfg->block_count); + } + + *block = nblock; + *off = 4*skips; + return 0; + } + +relocate: + LFS1_DEBUG("Bad block at %" PRIu32, nblock); + + // just clear cache and try a new block + lfs1_cache_drop(lfs1, &lfs1->pcache); + } +} + +static int lfs1_ctz_traverse(lfs1_t *lfs1, + lfs1_cache_t *rcache, const lfs1_cache_t *pcache, + lfs1_block_t head, lfs1_size_t size, + int (*cb)(void*, lfs1_block_t), void *data) { + if (size == 0) { + return 0; + } + + lfs1_off_t index = lfs1_ctz_index(lfs1, &(lfs1_off_t){size-1}); + + while (true) { + int err = cb(data, head); + if (err) { + return err; + } + + if (index == 0) { + return 0; + } + + lfs1_block_t heads[2]; + int count = 2 - (index & 1); + err = lfs1_cache_read(lfs1, rcache, pcache, head, 0, &heads, count*4); + heads[0] = lfs1_fromle32(heads[0]); + heads[1] = lfs1_fromle32(heads[1]); + if (err) { + return err; + } + + for (int i = 0; i < count-1; i++) { + err = cb(data, heads[i]); + if (err) { + return err; + } + } + + head = heads[count-1]; + index -= count; + } +} + + +/// Top level file operations /// +int lfs1_file_opencfg(lfs1_t *lfs1, lfs1_file_t *file, + const char *path, int flags, + const struct lfs1_file_config *cfg) { + // deorphan if we haven't yet, needed at most once after poweron + if ((flags & 3) != LFS1_O_RDONLY && !lfs1->deorphaned) { + int err = lfs1_deorphan(lfs1); + if (err) { + return err; + } + } + + // allocate entry for file if it doesn't exist + lfs1_dir_t cwd; + lfs1_entry_t entry; + int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); + if (err && (err != LFS1_ERR_NOENT || strchr(path, '/') != NULL)) { + return err; + } + + if (err == LFS1_ERR_NOENT) { + if (!(flags & LFS1_O_CREAT)) { + return LFS1_ERR_NOENT; + } + + // create entry to remember name + entry.d.type = LFS1_TYPE_REG; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = 0; + entry.d.nlen = strlen(path); + entry.d.u.file.head = 0xffffffff; + entry.d.u.file.size = 0; + err = lfs1_dir_append(lfs1, &cwd, &entry, path); + if (err) { + return err; + } + } else if (entry.d.type == LFS1_TYPE_DIR) { + return LFS1_ERR_ISDIR; + } else if (flags & LFS1_O_EXCL) { + return LFS1_ERR_EXIST; + } + + // setup file struct + file->cfg = cfg; + file->pair[0] = cwd.pair[0]; + file->pair[1] = cwd.pair[1]; + file->poff = entry.off; + file->head = entry.d.u.file.head; + file->size = entry.d.u.file.size; + file->flags = flags; + file->pos = 0; + + if (flags & LFS1_O_TRUNC) { + if (file->size != 0) { + file->flags |= LFS1_F_DIRTY; + } + file->head = 0xffffffff; + file->size = 0; + } + + // allocate buffer if needed + file->cache.block = 0xffffffff; + if (file->cfg && file->cfg->buffer) { + file->cache.buffer = file->cfg->buffer; + } else if (lfs1->cfg->file_buffer) { + if (lfs1->files) { + // already in use + return LFS1_ERR_NOMEM; + } + file->cache.buffer = lfs1->cfg->file_buffer; + } else if ((file->flags & 3) == LFS1_O_RDONLY) { + file->cache.buffer = lfs1_malloc(lfs1->cfg->read_size); + if (!file->cache.buffer) { + return LFS1_ERR_NOMEM; + } + } else { + file->cache.buffer = lfs1_malloc(lfs1->cfg->prog_size); + if (!file->cache.buffer) { + return LFS1_ERR_NOMEM; + } + } + + // zero to avoid information leak + lfs1_cache_drop(lfs1, &file->cache); + if ((file->flags & 3) != LFS1_O_RDONLY) { + lfs1_cache_zero(lfs1, &file->cache); + } + + // add to list of files + file->next = lfs1->files; + lfs1->files = file; + + return 0; +} + +int lfs1_file_open(lfs1_t *lfs1, lfs1_file_t *file, + const char *path, int flags) { + return lfs1_file_opencfg(lfs1, file, path, flags, NULL); +} + +int lfs1_file_close(lfs1_t *lfs1, lfs1_file_t *file) { + int err = lfs1_file_sync(lfs1, file); + + // remove from list of files + for (lfs1_file_t **p = &lfs1->files; *p; p = &(*p)->next) { + if (*p == file) { + *p = file->next; + break; + } + } + + // clean up memory + if (!(file->cfg && file->cfg->buffer) && !lfs1->cfg->file_buffer) { + lfs1_free(file->cache.buffer); + } + + return err; +} + +static int lfs1_file_relocate(lfs1_t *lfs1, lfs1_file_t *file) { +relocate: + LFS1_DEBUG("Bad block at %" PRIu32, file->block); + + // just relocate what exists into new block + lfs1_block_t nblock; + int err = lfs1_alloc(lfs1, &nblock); + if (err) { + return err; + } + + err = lfs1_bd_erase(lfs1, nblock); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // either read from dirty cache or disk + for (lfs1_off_t i = 0; i < file->off; i++) { + uint8_t data; + err = lfs1_cache_read(lfs1, &lfs1->rcache, &file->cache, + file->block, i, &data, 1); + if (err) { + return err; + } + + err = lfs1_cache_prog(lfs1, &lfs1->pcache, &lfs1->rcache, + nblock, i, &data, 1); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + // copy over new state of file + memcpy(file->cache.buffer, lfs1->pcache.buffer, lfs1->cfg->prog_size); + file->cache.block = lfs1->pcache.block; + file->cache.off = lfs1->pcache.off; + lfs1_cache_zero(lfs1, &lfs1->pcache); + + file->block = nblock; + return 0; +} + +static int lfs1_file_flush(lfs1_t *lfs1, lfs1_file_t *file) { + if (file->flags & LFS1_F_READING) { + // just drop read cache + lfs1_cache_drop(lfs1, &file->cache); + file->flags &= ~LFS1_F_READING; + } + + if (file->flags & LFS1_F_WRITING) { + lfs1_off_t pos = file->pos; + + // copy over anything after current branch + lfs1_file_t orig = { + .head = file->head, + .size = file->size, + .flags = LFS1_O_RDONLY, + .pos = file->pos, + .cache = lfs1->rcache, + }; + lfs1_cache_drop(lfs1, &lfs1->rcache); + + while (file->pos < file->size) { + // copy over a byte at a time, leave it up to caching + // to make this efficient + uint8_t data; + lfs1_ssize_t res = lfs1_file_read(lfs1, &orig, &data, 1); + if (res < 0) { + return res; + } + + res = lfs1_file_write(lfs1, file, &data, 1); + if (res < 0) { + return res; + } + + // keep our reference to the rcache in sync + if (lfs1->rcache.block != 0xffffffff) { + lfs1_cache_drop(lfs1, &orig.cache); + lfs1_cache_drop(lfs1, &lfs1->rcache); + } + } + + // write out what we have + while (true) { + int err = lfs1_cache_flush(lfs1, &file->cache, &lfs1->rcache); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + break; +relocate: + err = lfs1_file_relocate(lfs1, file); + if (err) { + return err; + } + } + + // actual file updates + file->head = file->block; + file->size = file->pos; + file->flags &= ~LFS1_F_WRITING; + file->flags |= LFS1_F_DIRTY; + + file->pos = pos; + } + + return 0; +} + +int lfs1_file_sync(lfs1_t *lfs1, lfs1_file_t *file) { + int err = lfs1_file_flush(lfs1, file); + if (err) { + return err; + } + + if ((file->flags & LFS1_F_DIRTY) && + !(file->flags & LFS1_F_ERRED) && + !lfs1_pairisnull(file->pair)) { + // update dir entry + lfs1_dir_t cwd; + err = lfs1_dir_fetch(lfs1, &cwd, file->pair); + if (err) { + return err; + } + + lfs1_entry_t entry = {.off = file->poff}; + err = lfs1_bd_read(lfs1, cwd.pair[0], entry.off, + &entry.d, sizeof(entry.d)); + lfs1_entry_fromle32(&entry.d); + if (err) { + return err; + } + + LFS1_ASSERT(entry.d.type == LFS1_TYPE_REG); + entry.d.u.file.head = file->head; + entry.d.u.file.size = file->size; + + err = lfs1_dir_update(lfs1, &cwd, &entry, NULL); + if (err) { + return err; + } + + file->flags &= ~LFS1_F_DIRTY; + } + + return 0; +} + +lfs1_ssize_t lfs1_file_read(lfs1_t *lfs1, lfs1_file_t *file, + void *buffer, lfs1_size_t size) { + uint8_t *data = buffer; + lfs1_size_t nsize = size; + + if ((file->flags & 3) == LFS1_O_WRONLY) { + return LFS1_ERR_BADF; + } + + if (file->flags & LFS1_F_WRITING) { + // flush out any writes + int err = lfs1_file_flush(lfs1, file); + if (err) { + return err; + } + } + + if (file->pos >= file->size) { + // eof if past end + return 0; + } + + size = lfs1_min(size, file->size - file->pos); + nsize = size; + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS1_F_READING) || + file->off == lfs1->cfg->block_size) { + int err = lfs1_ctz_find(lfs1, &file->cache, NULL, + file->head, file->size, + file->pos, &file->block, &file->off); + if (err) { + return err; + } + + file->flags |= LFS1_F_READING; + } + + // read as much as we can in current block + lfs1_size_t diff = lfs1_min(nsize, lfs1->cfg->block_size - file->off); + int err = lfs1_cache_read(lfs1, &file->cache, NULL, + file->block, file->off, data, diff); + if (err) { + return err; + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + } + + return size; +} + +lfs1_ssize_t lfs1_file_write(lfs1_t *lfs1, lfs1_file_t *file, + const void *buffer, lfs1_size_t size) { + const uint8_t *data = buffer; + lfs1_size_t nsize = size; + + if ((file->flags & 3) == LFS1_O_RDONLY) { + return LFS1_ERR_BADF; + } + + if (file->flags & LFS1_F_READING) { + // drop any reads + int err = lfs1_file_flush(lfs1, file); + if (err) { + return err; + } + } + + if ((file->flags & LFS1_O_APPEND) && file->pos < file->size) { + file->pos = file->size; + } + + if (file->pos + size > LFS1_FILE_MAX) { + // larger than file limit? + return LFS1_ERR_FBIG; + } + + if (!(file->flags & LFS1_F_WRITING) && file->pos > file->size) { + // fill with zeros + lfs1_off_t pos = file->pos; + file->pos = file->size; + + while (file->pos < pos) { + lfs1_ssize_t res = lfs1_file_write(lfs1, file, &(uint8_t){0}, 1); + if (res < 0) { + return res; + } + } + } + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS1_F_WRITING) || + file->off == lfs1->cfg->block_size) { + if (!(file->flags & LFS1_F_WRITING) && file->pos > 0) { + // find out which block we're extending from + int err = lfs1_ctz_find(lfs1, &file->cache, NULL, + file->head, file->size, + file->pos-1, &file->block, &file->off); + if (err) { + file->flags |= LFS1_F_ERRED; + return err; + } + + // mark cache as dirty since we may have read data into it + lfs1_cache_zero(lfs1, &file->cache); + } + + // extend file with new blocks + lfs1_alloc_ack(lfs1); + int err = lfs1_ctz_extend(lfs1, &lfs1->rcache, &file->cache, + file->block, file->pos, + &file->block, &file->off); + if (err) { + file->flags |= LFS1_F_ERRED; + return err; + } + + file->flags |= LFS1_F_WRITING; + } + + // program as much as we can in current block + lfs1_size_t diff = lfs1_min(nsize, lfs1->cfg->block_size - file->off); + while (true) { + int err = lfs1_cache_prog(lfs1, &file->cache, &lfs1->rcache, + file->block, file->off, data, diff); + if (err) { + if (err == LFS1_ERR_CORRUPT) { + goto relocate; + } + file->flags |= LFS1_F_ERRED; + return err; + } + + break; +relocate: + err = lfs1_file_relocate(lfs1, file); + if (err) { + file->flags |= LFS1_F_ERRED; + return err; + } + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + + lfs1_alloc_ack(lfs1); + } + + file->flags &= ~LFS1_F_ERRED; + return size; +} + +lfs1_soff_t lfs1_file_seek(lfs1_t *lfs1, lfs1_file_t *file, + lfs1_soff_t off, int whence) { + // write out everything beforehand, may be noop if rdonly + int err = lfs1_file_flush(lfs1, file); + if (err) { + return err; + } + + // find new pos + lfs1_soff_t npos = file->pos; + if (whence == LFS1_SEEK_SET) { + npos = off; + } else if (whence == LFS1_SEEK_CUR) { + npos = file->pos + off; + } else if (whence == LFS1_SEEK_END) { + npos = file->size + off; + } + + if (npos < 0 || npos > LFS1_FILE_MAX) { + // file position out of range + return LFS1_ERR_INVAL; + } + + // update pos + file->pos = npos; + return npos; +} + +int lfs1_file_truncate(lfs1_t *lfs1, lfs1_file_t *file, lfs1_off_t size) { + if ((file->flags & 3) == LFS1_O_RDONLY) { + return LFS1_ERR_BADF; + } + + lfs1_off_t oldsize = lfs1_file_size(lfs1, file); + if (size < oldsize) { + // need to flush since directly changing metadata + int err = lfs1_file_flush(lfs1, file); + if (err) { + return err; + } + + // lookup new head in ctz skip list + err = lfs1_ctz_find(lfs1, &file->cache, NULL, + file->head, file->size, + size, &file->head, &(lfs1_off_t){0}); + if (err) { + return err; + } + + file->size = size; + file->flags |= LFS1_F_DIRTY; + } else if (size > oldsize) { + lfs1_off_t pos = file->pos; + + // flush+seek if not already at end + if (file->pos != oldsize) { + int err = lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_END); + if (err < 0) { + return err; + } + } + + // fill with zeros + while (file->pos < size) { + lfs1_ssize_t res = lfs1_file_write(lfs1, file, &(uint8_t){0}, 1); + if (res < 0) { + return res; + } + } + + // restore pos + int err = lfs1_file_seek(lfs1, file, pos, LFS1_SEEK_SET); + if (err < 0) { + return err; + } + } + + return 0; +} + +lfs1_soff_t lfs1_file_tell(lfs1_t *lfs1, lfs1_file_t *file) { + (void)lfs1; + return file->pos; +} + +int lfs1_file_rewind(lfs1_t *lfs1, lfs1_file_t *file) { + lfs1_soff_t res = lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_SET); + if (res < 0) { + return res; + } + + return 0; +} + +lfs1_soff_t lfs1_file_size(lfs1_t *lfs1, lfs1_file_t *file) { + (void)lfs1; + if (file->flags & LFS1_F_WRITING) { + return lfs1_max(file->pos, file->size); + } else { + return file->size; + } +} + + +/// General fs operations /// +int lfs1_stat(lfs1_t *lfs1, const char *path, struct lfs1_info *info) { + lfs1_dir_t cwd; + lfs1_entry_t entry; + int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); + if (err) { + return err; + } + + memset(info, 0, sizeof(*info)); + info->type = entry.d.type; + if (info->type == LFS1_TYPE_REG) { + info->size = entry.d.u.file.size; + } + + if (lfs1_paircmp(entry.d.u.dir, lfs1->root) == 0) { + strcpy(info->name, "/"); + } else { + err = lfs1_bd_read(lfs1, cwd.pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); + if (err) { + return err; + } + } + + return 0; +} + +int lfs1_remove(lfs1_t *lfs1, const char *path) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs1->deorphaned) { + int err = lfs1_deorphan(lfs1); + if (err) { + return err; + } + } + + lfs1_dir_t cwd; + lfs1_entry_t entry; + int err = lfs1_dir_find(lfs1, &cwd, &entry, &path); + if (err) { + return err; + } + + lfs1_dir_t dir; + if (entry.d.type == LFS1_TYPE_DIR) { + // must be empty before removal, checking size + // without masking top bit checks for any case where + // dir is not empty + err = lfs1_dir_fetch(lfs1, &dir, entry.d.u.dir); + if (err) { + return err; + } else if (dir.d.size != sizeof(dir.d)+4) { + return LFS1_ERR_NOTEMPTY; + } + } + + // remove the entry + err = lfs1_dir_remove(lfs1, &cwd, &entry); + if (err) { + return err; + } + + // if we were a directory, find pred, replace tail + if (entry.d.type == LFS1_TYPE_DIR) { + int res = lfs1_pred(lfs1, dir.pair, &cwd); + if (res < 0) { + return res; + } + + LFS1_ASSERT(res); // must have pred + cwd.d.tail[0] = dir.d.tail[0]; + cwd.d.tail[1] = dir.d.tail[1]; + + err = lfs1_dir_commit(lfs1, &cwd, NULL, 0); + if (err) { + return err; + } + } + + return 0; +} + +int lfs1_rename(lfs1_t *lfs1, const char *oldpath, const char *newpath) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs1->deorphaned) { + int err = lfs1_deorphan(lfs1); + if (err) { + return err; + } + } + + // find old entry + lfs1_dir_t oldcwd; + lfs1_entry_t oldentry; + int err = lfs1_dir_find(lfs1, &oldcwd, &oldentry, &(const char *){oldpath}); + if (err) { + return err; + } + + // mark as moving + oldentry.d.type |= 0x80; + err = lfs1_dir_update(lfs1, &oldcwd, &oldentry, NULL); + if (err) { + return err; + } + + // allocate new entry + lfs1_dir_t newcwd; + lfs1_entry_t preventry; + err = lfs1_dir_find(lfs1, &newcwd, &preventry, &newpath); + if (err && (err != LFS1_ERR_NOENT || strchr(newpath, '/') != NULL)) { + return err; + } + + // must have same type + bool prevexists = (err != LFS1_ERR_NOENT); + if (prevexists && preventry.d.type != (0x7f & oldentry.d.type)) { + return LFS1_ERR_ISDIR; + } + + lfs1_dir_t dir; + if (prevexists && preventry.d.type == LFS1_TYPE_DIR) { + // must be empty before removal, checking size + // without masking top bit checks for any case where + // dir is not empty + err = lfs1_dir_fetch(lfs1, &dir, preventry.d.u.dir); + if (err) { + return err; + } else if (dir.d.size != sizeof(dir.d)+4) { + return LFS1_ERR_NOTEMPTY; + } + } + + // move to new location + lfs1_entry_t newentry = preventry; + newentry.d = oldentry.d; + newentry.d.type &= ~0x80; + newentry.d.nlen = strlen(newpath); + + if (prevexists) { + err = lfs1_dir_update(lfs1, &newcwd, &newentry, newpath); + if (err) { + return err; + } + } else { + err = lfs1_dir_append(lfs1, &newcwd, &newentry, newpath); + if (err) { + return err; + } + } + + // fetch old pair again in case dir block changed + lfs1->moving = true; + err = lfs1_dir_find(lfs1, &oldcwd, &oldentry, &oldpath); + if (err) { + return err; + } + lfs1->moving = false; + + // remove old entry + err = lfs1_dir_remove(lfs1, &oldcwd, &oldentry); + if (err) { + return err; + } + + // if we were a directory, find pred, replace tail + if (prevexists && preventry.d.type == LFS1_TYPE_DIR) { + int res = lfs1_pred(lfs1, dir.pair, &newcwd); + if (res < 0) { + return res; + } + + LFS1_ASSERT(res); // must have pred + newcwd.d.tail[0] = dir.d.tail[0]; + newcwd.d.tail[1] = dir.d.tail[1]; + + err = lfs1_dir_commit(lfs1, &newcwd, NULL, 0); + if (err) { + return err; + } + } + + return 0; +} + + +/// Filesystem operations /// +static void lfs1_deinit(lfs1_t *lfs1) { + // free allocated memory + if (!lfs1->cfg->read_buffer) { + lfs1_free(lfs1->rcache.buffer); + } + + if (!lfs1->cfg->prog_buffer) { + lfs1_free(lfs1->pcache.buffer); + } + + if (!lfs1->cfg->lookahead_buffer) { + lfs1_free(lfs1->free.buffer); + } +} + +static int lfs1_init(lfs1_t *lfs1, const struct lfs1_config *cfg) { + lfs1->cfg = cfg; + + // setup read cache + if (lfs1->cfg->read_buffer) { + lfs1->rcache.buffer = lfs1->cfg->read_buffer; + } else { + lfs1->rcache.buffer = lfs1_malloc(lfs1->cfg->read_size); + if (!lfs1->rcache.buffer) { + goto cleanup; + } + } + + // setup program cache + if (lfs1->cfg->prog_buffer) { + lfs1->pcache.buffer = lfs1->cfg->prog_buffer; + } else { + lfs1->pcache.buffer = lfs1_malloc(lfs1->cfg->prog_size); + if (!lfs1->pcache.buffer) { + goto cleanup; + } + } + + // zero to avoid information leaks + lfs1_cache_zero(lfs1, &lfs1->pcache); + lfs1_cache_drop(lfs1, &lfs1->rcache); + + // setup lookahead, round down to nearest 32-bits + LFS1_ASSERT(lfs1->cfg->lookahead % 32 == 0); + LFS1_ASSERT(lfs1->cfg->lookahead > 0); + if (lfs1->cfg->lookahead_buffer) { + lfs1->free.buffer = lfs1->cfg->lookahead_buffer; + } else { + lfs1->free.buffer = lfs1_malloc(lfs1->cfg->lookahead/8); + if (!lfs1->free.buffer) { + goto cleanup; + } + } + + // check that program and read sizes are multiples of the block size + LFS1_ASSERT(lfs1->cfg->prog_size % lfs1->cfg->read_size == 0); + LFS1_ASSERT(lfs1->cfg->block_size % lfs1->cfg->prog_size == 0); + + // check that the block size is large enough to fit ctz pointers + LFS1_ASSERT(4*lfs1_npw2(0xffffffff / (lfs1->cfg->block_size-2*4)) + <= lfs1->cfg->block_size); + + // setup default state + lfs1->root[0] = 0xffffffff; + lfs1->root[1] = 0xffffffff; + lfs1->files = NULL; + lfs1->dirs = NULL; + lfs1->deorphaned = false; + lfs1->moving = false; + + return 0; + +cleanup: + lfs1_deinit(lfs1); + return LFS1_ERR_NOMEM; +} + +int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *cfg) { + int err = 0; + if (true) { + err = lfs1_init(lfs1, cfg); + if (err) { + return err; + } + + // create free lookahead + memset(lfs1->free.buffer, 0, lfs1->cfg->lookahead/8); + lfs1->free.off = 0; + lfs1->free.size = lfs1_min(lfs1->cfg->lookahead, lfs1->cfg->block_count); + lfs1->free.i = 0; + lfs1_alloc_ack(lfs1); + + // create superblock dir + lfs1_dir_t superdir; + err = lfs1_dir_alloc(lfs1, &superdir); + if (err) { + goto cleanup; + } + + // write root directory + lfs1_dir_t root; + err = lfs1_dir_alloc(lfs1, &root); + if (err) { + goto cleanup; + } + + err = lfs1_dir_commit(lfs1, &root, NULL, 0); + if (err) { + goto cleanup; + } + + lfs1->root[0] = root.pair[0]; + lfs1->root[1] = root.pair[1]; + + // write superblocks + lfs1_superblock_t superblock = { + .off = sizeof(superdir.d), + .d.type = LFS1_TYPE_SUPERBLOCK, + .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, + .d.nlen = sizeof(superblock.d.magic), + .d.version = LFS1_DISK_VERSION, + .d.magic = {"littlefs"}, + .d.block_size = lfs1->cfg->block_size, + .d.block_count = lfs1->cfg->block_count, + .d.root = {lfs1->root[0], lfs1->root[1]}, + }; + superdir.d.tail[0] = root.pair[0]; + superdir.d.tail[1] = root.pair[1]; + superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4; + + // write both pairs to be safe + lfs1_superblock_tole32(&superblock.d); + bool valid = false; + for (int i = 0; i < 2; i++) { + err = lfs1_dir_commit(lfs1, &superdir, (struct lfs1_region[]){ + {sizeof(superdir.d), sizeof(superblock.d), + &superblock.d, sizeof(superblock.d)} + }, 1); + if (err && err != LFS1_ERR_CORRUPT) { + goto cleanup; + } + + valid = valid || !err; + } + + if (!valid) { + err = LFS1_ERR_CORRUPT; + goto cleanup; + } + + // sanity check that fetch works + err = lfs1_dir_fetch(lfs1, &superdir, (const lfs1_block_t[2]){0, 1}); + if (err) { + goto cleanup; + } + + lfs1_alloc_ack(lfs1); + } + +cleanup: + lfs1_deinit(lfs1); + return err; +} + +int lfs1_mount(lfs1_t *lfs1, const struct lfs1_config *cfg) { + int err = 0; + if (true) { + err = lfs1_init(lfs1, cfg); + if (err) { + return err; + } + + // setup free lookahead + lfs1->free.off = 0; + lfs1->free.size = 0; + lfs1->free.i = 0; + lfs1_alloc_ack(lfs1); + + // load superblock + lfs1_dir_t dir; + lfs1_superblock_t superblock; + err = lfs1_dir_fetch(lfs1, &dir, (const lfs1_block_t[2]){0, 1}); + if (err && err != LFS1_ERR_CORRUPT) { + goto cleanup; + } + + if (!err) { + err = lfs1_bd_read(lfs1, dir.pair[0], sizeof(dir.d), + &superblock.d, sizeof(superblock.d)); + lfs1_superblock_fromle32(&superblock.d); + if (err) { + goto cleanup; + } + + lfs1->root[0] = superblock.d.root[0]; + lfs1->root[1] = superblock.d.root[1]; + } + + if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) { + LFS1_ERROR("Invalid superblock at %d %d", 0, 1); + err = LFS1_ERR_CORRUPT; + goto cleanup; + } + + uint16_t major_version = (0xffff & (superblock.d.version >> 16)); + uint16_t minor_version = (0xffff & (superblock.d.version >> 0)); + if ((major_version != LFS1_DISK_VERSION_MAJOR || + minor_version > LFS1_DISK_VERSION_MINOR)) { + LFS1_ERROR("Invalid version %d.%d", major_version, minor_version); + err = LFS1_ERR_INVAL; + goto cleanup; + } + + return 0; + } + +cleanup: + + lfs1_deinit(lfs1); + return err; +} + +int lfs1_unmount(lfs1_t *lfs1) { + lfs1_deinit(lfs1); + return 0; +} + + +/// Littlefs specific operations /// +int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data) { + if (lfs1_pairisnull(lfs1->root)) { + return 0; + } + + // iterate over metadata pairs + lfs1_dir_t dir; + lfs1_entry_t entry; + lfs1_block_t cwd[2] = {0, 1}; + + while (true) { + for (int i = 0; i < 2; i++) { + int err = cb(data, cwd[i]); + if (err) { + return err; + } + } + + int err = lfs1_dir_fetch(lfs1, &dir, cwd); + if (err) { + return err; + } + + // iterate over contents + while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { + err = lfs1_bd_read(lfs1, dir.pair[0], dir.off, + &entry.d, sizeof(entry.d)); + lfs1_entry_fromle32(&entry.d); + if (err) { + return err; + } + + dir.off += lfs1_entry_size(&entry); + if ((0x70 & entry.d.type) == (0x70 & LFS1_TYPE_REG)) { + err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, NULL, + entry.d.u.file.head, entry.d.u.file.size, cb, data); + if (err) { + return err; + } + } + } + + cwd[0] = dir.d.tail[0]; + cwd[1] = dir.d.tail[1]; + + if (lfs1_pairisnull(cwd)) { + break; + } + } + + // iterate over any open files + for (lfs1_file_t *f = lfs1->files; f; f = f->next) { + if (f->flags & LFS1_F_DIRTY) { + int err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, &f->cache, + f->head, f->size, cb, data); + if (err) { + return err; + } + } + + if (f->flags & LFS1_F_WRITING) { + int err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, &f->cache, + f->block, f->pos, cb, data); + if (err) { + return err; + } + } + } + + return 0; +} + +static int lfs1_pred(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *pdir) { + if (lfs1_pairisnull(lfs1->root)) { + return 0; + } + + // iterate over all directory directory entries + int err = lfs1_dir_fetch(lfs1, pdir, (const lfs1_block_t[2]){0, 1}); + if (err) { + return err; + } + + while (!lfs1_pairisnull(pdir->d.tail)) { + if (lfs1_paircmp(pdir->d.tail, dir) == 0) { + return true; + } + + err = lfs1_dir_fetch(lfs1, pdir, pdir->d.tail); + if (err) { + return err; + } + } + + return false; +} + +static int lfs1_parent(lfs1_t *lfs1, const lfs1_block_t dir[2], + lfs1_dir_t *parent, lfs1_entry_t *entry) { + if (lfs1_pairisnull(lfs1->root)) { + return 0; + } + + parent->d.tail[0] = 0; + parent->d.tail[1] = 1; + + // iterate over all directory directory entries + while (!lfs1_pairisnull(parent->d.tail)) { + int err = lfs1_dir_fetch(lfs1, parent, parent->d.tail); + if (err) { + return err; + } + + while (true) { + err = lfs1_dir_next(lfs1, parent, entry); + if (err && err != LFS1_ERR_NOENT) { + return err; + } + + if (err == LFS1_ERR_NOENT) { + break; + } + + if (((0x70 & entry->d.type) == (0x70 & LFS1_TYPE_DIR)) && + lfs1_paircmp(entry->d.u.dir, dir) == 0) { + return true; + } + } + } + + return false; +} + +static int lfs1_moved(lfs1_t *lfs1, const void *e) { + if (lfs1_pairisnull(lfs1->root)) { + return 0; + } + + // skip superblock + lfs1_dir_t cwd; + int err = lfs1_dir_fetch(lfs1, &cwd, (const lfs1_block_t[2]){0, 1}); + if (err) { + return err; + } + + // iterate over all directory directory entries + lfs1_entry_t entry; + while (!lfs1_pairisnull(cwd.d.tail)) { + err = lfs1_dir_fetch(lfs1, &cwd, cwd.d.tail); + if (err) { + return err; + } + + while (true) { + err = lfs1_dir_next(lfs1, &cwd, &entry); + if (err && err != LFS1_ERR_NOENT) { + return err; + } + + if (err == LFS1_ERR_NOENT) { + break; + } + + if (!(0x80 & entry.d.type) && + memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) { + return true; + } + } + } + + return false; +} + +static int lfs1_relocate(lfs1_t *lfs1, + const lfs1_block_t oldpair[2], const lfs1_block_t newpair[2]) { + // find parent + lfs1_dir_t parent; + lfs1_entry_t entry; + int res = lfs1_parent(lfs1, oldpair, &parent, &entry); + if (res < 0) { + return res; + } + + if (res) { + // update disk, this creates a desync + entry.d.u.dir[0] = newpair[0]; + entry.d.u.dir[1] = newpair[1]; + + int err = lfs1_dir_update(lfs1, &parent, &entry, NULL); + if (err) { + return err; + } + + // update internal root + if (lfs1_paircmp(oldpair, lfs1->root) == 0) { + LFS1_DEBUG("Relocating root %" PRIu32 " %" PRIu32, + newpair[0], newpair[1]); + lfs1->root[0] = newpair[0]; + lfs1->root[1] = newpair[1]; + } + + // clean up bad block, which should now be a desync + return lfs1_deorphan(lfs1); + } + + // find pred + res = lfs1_pred(lfs1, oldpair, &parent); + if (res < 0) { + return res; + } + + if (res) { + // just replace bad pair, no desync can occur + parent.d.tail[0] = newpair[0]; + parent.d.tail[1] = newpair[1]; + + return lfs1_dir_commit(lfs1, &parent, NULL, 0); + } + + // couldn't find dir, must be new + return 0; +} + +int lfs1_deorphan(lfs1_t *lfs1) { + lfs1->deorphaned = true; + + if (lfs1_pairisnull(lfs1->root)) { + return 0; + } + + lfs1_dir_t pdir = {.d.size = 0x80000000}; + lfs1_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1}; + + // iterate over all directory directory entries + for (lfs1_size_t i = 0; i < lfs1->cfg->block_count; i++) { + if (lfs1_pairisnull(cwd.d.tail)) { + return 0; + } + + int err = lfs1_dir_fetch(lfs1, &cwd, cwd.d.tail); + if (err) { + return err; + } + + // check head blocks for orphans + if (!(0x80000000 & pdir.d.size)) { + // check if we have a parent + lfs1_dir_t parent; + lfs1_entry_t entry; + int res = lfs1_parent(lfs1, pdir.d.tail, &parent, &entry); + if (res < 0) { + return res; + } + + if (!res) { + // we are an orphan + LFS1_DEBUG("Found orphan %" PRIu32 " %" PRIu32, + pdir.d.tail[0], pdir.d.tail[1]); + + pdir.d.tail[0] = cwd.d.tail[0]; + pdir.d.tail[1] = cwd.d.tail[1]; + + err = lfs1_dir_commit(lfs1, &pdir, NULL, 0); + if (err) { + return err; + } + + return 0; + } + + if (!lfs1_pairsync(entry.d.u.dir, pdir.d.tail)) { + // we have desynced + LFS1_DEBUG("Found desync %" PRIu32 " %" PRIu32, + entry.d.u.dir[0], entry.d.u.dir[1]); + + pdir.d.tail[0] = entry.d.u.dir[0]; + pdir.d.tail[1] = entry.d.u.dir[1]; + + err = lfs1_dir_commit(lfs1, &pdir, NULL, 0); + if (err) { + return err; + } + + return 0; + } + } + + // check entries for moves + lfs1_entry_t entry; + while (true) { + err = lfs1_dir_next(lfs1, &cwd, &entry); + if (err && err != LFS1_ERR_NOENT) { + return err; + } + + if (err == LFS1_ERR_NOENT) { + break; + } + + // found moved entry + if (entry.d.type & 0x80) { + int moved = lfs1_moved(lfs1, &entry.d.u); + if (moved < 0) { + return moved; + } + + if (moved) { + LFS1_DEBUG("Found move %" PRIu32 " %" PRIu32, + entry.d.u.dir[0], entry.d.u.dir[1]); + err = lfs1_dir_remove(lfs1, &cwd, &entry); + if (err) { + return err; + } + } else { + LFS1_DEBUG("Found partial move %" PRIu32 " %" PRIu32, + entry.d.u.dir[0], entry.d.u.dir[1]); + entry.d.type &= ~0x80; + err = lfs1_dir_update(lfs1, &cwd, &entry, NULL); + if (err) { + return err; + } + } + } + } + + memcpy(&pdir, &cwd, sizeof(pdir)); + } + + // If we reached here, we have more directory pairs than blocks in the + // filesystem... So something must be horribly wrong + return LFS1_ERR_CORRUPT; +} diff --git a/lib/littlefs/lfs1.h b/lib/littlefs/lfs1.h new file mode 100644 index 0000000000000..355c145d08722 --- /dev/null +++ b/lib/littlefs/lfs1.h @@ -0,0 +1,501 @@ +/* + * The little filesystem + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LFS1_H +#define LFS1_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/// Version info /// + +// Software library version +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS1_VERSION 0x00010007 +#define LFS1_VERSION_MAJOR (0xffff & (LFS1_VERSION >> 16)) +#define LFS1_VERSION_MINOR (0xffff & (LFS1_VERSION >> 0)) + +// Version of On-disk data structures +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS1_DISK_VERSION 0x00010001 +#define LFS1_DISK_VERSION_MAJOR (0xffff & (LFS1_DISK_VERSION >> 16)) +#define LFS1_DISK_VERSION_MINOR (0xffff & (LFS1_DISK_VERSION >> 0)) + + +/// Definitions /// + +// Type definitions +typedef uint32_t lfs1_size_t; +typedef uint32_t lfs1_off_t; + +typedef int32_t lfs1_ssize_t; +typedef int32_t lfs1_soff_t; + +typedef uint32_t lfs1_block_t; + +// Max name size in bytes +#ifndef LFS1_NAME_MAX +#define LFS1_NAME_MAX 255 +#endif + +// Max file size in bytes +#ifndef LFS1_FILE_MAX +#define LFS1_FILE_MAX 2147483647 +#endif + +// Possible error codes, these are negative to allow +// valid positive return values +enum lfs1_error { + LFS1_ERR_OK = 0, // No error + LFS1_ERR_IO = -5, // Error during device operation + LFS1_ERR_CORRUPT = -52, // Corrupted + LFS1_ERR_NOENT = -2, // No directory entry + LFS1_ERR_EXIST = -17, // Entry already exists + LFS1_ERR_NOTDIR = -20, // Entry is not a dir + LFS1_ERR_ISDIR = -21, // Entry is a dir + LFS1_ERR_NOTEMPTY = -39, // Dir is not empty + LFS1_ERR_BADF = -9, // Bad file number + LFS1_ERR_FBIG = -27, // File too large + LFS1_ERR_INVAL = -22, // Invalid parameter + LFS1_ERR_NOSPC = -28, // No space left on device + LFS1_ERR_NOMEM = -12, // No more memory available +}; + +// File types +enum lfs1_type { + LFS1_TYPE_REG = 0x11, + LFS1_TYPE_DIR = 0x22, + LFS1_TYPE_SUPERBLOCK = 0x2e, +}; + +// File open flags +enum lfs1_open_flags { + // open flags + LFS1_O_RDONLY = 1, // Open a file as read only + LFS1_O_WRONLY = 2, // Open a file as write only + LFS1_O_RDWR = 3, // Open a file as read and write + LFS1_O_CREAT = 0x0100, // Create a file if it does not exist + LFS1_O_EXCL = 0x0200, // Fail if a file already exists + LFS1_O_TRUNC = 0x0400, // Truncate the existing file to zero size + LFS1_O_APPEND = 0x0800, // Move to end of file on every write + + // internally used flags + LFS1_F_DIRTY = 0x10000, // File does not match storage + LFS1_F_WRITING = 0x20000, // File has been written since last flush + LFS1_F_READING = 0x40000, // File has been read since last flush + LFS1_F_ERRED = 0x80000, // An error occured during write +}; + +// File seek flags +enum lfs1_whence_flags { + LFS1_SEEK_SET = 0, // Seek relative to an absolute position + LFS1_SEEK_CUR = 1, // Seek relative to the current file position + LFS1_SEEK_END = 2, // Seek relative to the end of the file +}; + + +// Configuration provided during initialization of the littlefs +struct lfs1_config { + // Opaque user provided context that can be used to pass + // information to the block device operations + void *context; + + // Read a region in a block. Negative error codes are propogated + // to the user. + int (*read)(const struct lfs1_config *c, lfs1_block_t block, + lfs1_off_t off, void *buffer, lfs1_size_t size); + + // Program a region in a block. The block must have previously + // been erased. Negative error codes are propogated to the user. + // May return LFS1_ERR_CORRUPT if the block should be considered bad. + int (*prog)(const struct lfs1_config *c, lfs1_block_t block, + lfs1_off_t off, const void *buffer, lfs1_size_t size); + + // Erase a block. A block must be erased before being programmed. + // The state of an erased block is undefined. Negative error codes + // are propogated to the user. + // May return LFS1_ERR_CORRUPT if the block should be considered bad. + int (*erase)(const struct lfs1_config *c, lfs1_block_t block); + + // Sync the state of the underlying block device. Negative error codes + // are propogated to the user. + int (*sync)(const struct lfs1_config *c); + + // Minimum size of a block read. This determines the size of read buffers. + // This may be larger than the physical read size to improve performance + // by caching more of the block device. + lfs1_size_t read_size; + + // Minimum size of a block program. This determines the size of program + // buffers. This may be larger than the physical program size to improve + // performance by caching more of the block device. + // Must be a multiple of the read size. + lfs1_size_t prog_size; + + // Size of an erasable block. This does not impact ram consumption and + // may be larger than the physical erase size. However, this should be + // kept small as each file currently takes up an entire block. + // Must be a multiple of the program size. + lfs1_size_t block_size; + + // Number of erasable blocks on the device. + lfs1_size_t block_count; + + // Number of blocks to lookahead during block allocation. A larger + // lookahead reduces the number of passes required to allocate a block. + // The lookahead buffer requires only 1 bit per block so it can be quite + // large with little ram impact. Should be a multiple of 32. + lfs1_size_t lookahead; + + // Optional, statically allocated read buffer. Must be read sized. + void *read_buffer; + + // Optional, statically allocated program buffer. Must be program sized. + void *prog_buffer; + + // Optional, statically allocated lookahead buffer. Must be 1 bit per + // lookahead block. + void *lookahead_buffer; + + // Optional, statically allocated buffer for files. Must be program sized. + // If enabled, only one file may be opened at a time. + void *file_buffer; +}; + +// Optional configuration provided during lfs1_file_opencfg +struct lfs1_file_config { + // Optional, statically allocated buffer for files. Must be program sized. + // If NULL, malloc will be used by default. + void *buffer; +}; + +// File info structure +struct lfs1_info { + // Type of the file, either LFS1_TYPE_REG or LFS1_TYPE_DIR + uint8_t type; + + // Size of the file, only valid for REG files + lfs1_size_t size; + + // Name of the file stored as a null-terminated string + char name[LFS1_NAME_MAX+1]; +}; + + +/// littlefs data structures /// +typedef struct lfs1_entry { + lfs1_off_t off; + + struct lfs1_disk_entry { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + union { + struct { + lfs1_block_t head; + lfs1_size_t size; + } file; + lfs1_block_t dir[2]; + } u; + } d; +} lfs1_entry_t; + +typedef struct lfs1_cache { + lfs1_block_t block; + lfs1_off_t off; + uint8_t *buffer; +} lfs1_cache_t; + +typedef struct lfs1_file { + struct lfs1_file *next; + lfs1_block_t pair[2]; + lfs1_off_t poff; + + lfs1_block_t head; + lfs1_size_t size; + + const struct lfs1_file_config *cfg; + uint32_t flags; + lfs1_off_t pos; + lfs1_block_t block; + lfs1_off_t off; + lfs1_cache_t cache; +} lfs1_file_t; + +typedef struct lfs1_dir { + struct lfs1_dir *next; + lfs1_block_t pair[2]; + lfs1_off_t off; + + lfs1_block_t head[2]; + lfs1_off_t pos; + + struct lfs1_disk_dir { + uint32_t rev; + lfs1_size_t size; + lfs1_block_t tail[2]; + } d; +} lfs1_dir_t; + +typedef struct lfs1_superblock { + lfs1_off_t off; + + struct lfs1_disk_superblock { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + lfs1_block_t root[2]; + uint32_t block_size; + uint32_t block_count; + uint32_t version; + char magic[8]; + } d; +} lfs1_superblock_t; + +typedef struct lfs1_free { + lfs1_block_t off; + lfs1_block_t size; + lfs1_block_t i; + lfs1_block_t ack; + uint32_t *buffer; +} lfs1_free_t; + +// The littlefs type +typedef struct lfs1 { + const struct lfs1_config *cfg; + + lfs1_block_t root[2]; + lfs1_file_t *files; + lfs1_dir_t *dirs; + + lfs1_cache_t rcache; + lfs1_cache_t pcache; + + lfs1_free_t free; + bool deorphaned; + bool moving; +} lfs1_t; + + +/// Filesystem functions /// + +// Format a block device with the littlefs +// +// Requires a littlefs object and config struct. This clobbers the littlefs +// object, and does not leave the filesystem mounted. The config struct must +// be zeroed for defaults and backwards compatibility. +// +// Returns a negative error code on failure. +int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *config); + +// Mounts a littlefs +// +// Requires a littlefs object and config struct. Multiple filesystems +// may be mounted simultaneously with multiple littlefs objects. Both +// lfs1 and config must be allocated while mounted. The config struct must +// be zeroed for defaults and backwards compatibility. +// +// Returns a negative error code on failure. +int lfs1_mount(lfs1_t *lfs1, const struct lfs1_config *config); + +// Unmounts a littlefs +// +// Does nothing besides releasing any allocated resources. +// Returns a negative error code on failure. +int lfs1_unmount(lfs1_t *lfs1); + +/// General operations /// + +// Removes a file or directory +// +// If removing a directory, the directory must be empty. +// Returns a negative error code on failure. +int lfs1_remove(lfs1_t *lfs1, const char *path); + +// Rename or move a file or directory +// +// If the destination exists, it must match the source in type. +// If the destination is a directory, the directory must be empty. +// +// Returns a negative error code on failure. +int lfs1_rename(lfs1_t *lfs1, const char *oldpath, const char *newpath); + +// Find info about a file or directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a negative error code on failure. +int lfs1_stat(lfs1_t *lfs1, const char *path, struct lfs1_info *info); + + +/// File operations /// + +// Open a file +// +// The mode that the file is opened in is determined by the flags, which +// are values from the enum lfs1_open_flags that are bitwise-ored together. +// +// Returns a negative error code on failure. +int lfs1_file_open(lfs1_t *lfs1, lfs1_file_t *file, + const char *path, int flags); + +// Open a file with extra configuration +// +// The mode that the file is opened in is determined by the flags, which +// are values from the enum lfs1_open_flags that are bitwise-ored together. +// +// The config struct provides additional config options per file as described +// above. The config struct must be allocated while the file is open, and the +// config struct must be zeroed for defaults and backwards compatibility. +// +// Returns a negative error code on failure. +int lfs1_file_opencfg(lfs1_t *lfs1, lfs1_file_t *file, + const char *path, int flags, + const struct lfs1_file_config *config); + +// Close a file +// +// Any pending writes are written out to storage as though +// sync had been called and releases any allocated resources. +// +// Returns a negative error code on failure. +int lfs1_file_close(lfs1_t *lfs1, lfs1_file_t *file); + +// Synchronize a file on storage +// +// Any pending writes are written out to storage. +// Returns a negative error code on failure. +int lfs1_file_sync(lfs1_t *lfs1, lfs1_file_t *file); + +// Read data from file +// +// Takes a buffer and size indicating where to store the read data. +// Returns the number of bytes read, or a negative error code on failure. +lfs1_ssize_t lfs1_file_read(lfs1_t *lfs1, lfs1_file_t *file, + void *buffer, lfs1_size_t size); + +// Write data to file +// +// Takes a buffer and size indicating the data to write. The file will not +// actually be updated on the storage until either sync or close is called. +// +// Returns the number of bytes written, or a negative error code on failure. +lfs1_ssize_t lfs1_file_write(lfs1_t *lfs1, lfs1_file_t *file, + const void *buffer, lfs1_size_t size); + +// Change the position of the file +// +// The change in position is determined by the offset and whence flag. +// Returns the old position of the file, or a negative error code on failure. +lfs1_soff_t lfs1_file_seek(lfs1_t *lfs1, lfs1_file_t *file, + lfs1_soff_t off, int whence); + +// Truncates the size of the file to the specified size +// +// Returns a negative error code on failure. +int lfs1_file_truncate(lfs1_t *lfs1, lfs1_file_t *file, lfs1_off_t size); + +// Return the position of the file +// +// Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR) +// Returns the position of the file, or a negative error code on failure. +lfs1_soff_t lfs1_file_tell(lfs1_t *lfs1, lfs1_file_t *file); + +// Change the position of the file to the beginning of the file +// +// Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR) +// Returns a negative error code on failure. +int lfs1_file_rewind(lfs1_t *lfs1, lfs1_file_t *file); + +// Return the size of the file +// +// Similar to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_END) +// Returns the size of the file, or a negative error code on failure. +lfs1_soff_t lfs1_file_size(lfs1_t *lfs1, lfs1_file_t *file); + + +/// Directory operations /// + +// Create a directory +// +// Returns a negative error code on failure. +int lfs1_mkdir(lfs1_t *lfs1, const char *path); + +// Open a directory +// +// Once open a directory can be used with read to iterate over files. +// Returns a negative error code on failure. +int lfs1_dir_open(lfs1_t *lfs1, lfs1_dir_t *dir, const char *path); + +// Close a directory +// +// Releases any allocated resources. +// Returns a negative error code on failure. +int lfs1_dir_close(lfs1_t *lfs1, lfs1_dir_t *dir); + +// Read an entry in the directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a negative error code on failure. +int lfs1_dir_read(lfs1_t *lfs1, lfs1_dir_t *dir, struct lfs1_info *info); + +// Change the position of the directory +// +// The new off must be a value previous returned from tell and specifies +// an absolute offset in the directory seek. +// +// Returns a negative error code on failure. +int lfs1_dir_seek(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_off_t off); + +// Return the position of the directory +// +// The returned offset is only meant to be consumed by seek and may not make +// sense, but does indicate the current position in the directory iteration. +// +// Returns the position of the directory, or a negative error code on failure. +lfs1_soff_t lfs1_dir_tell(lfs1_t *lfs1, lfs1_dir_t *dir); + +// Change the position of the directory to the beginning of the directory +// +// Returns a negative error code on failure. +int lfs1_dir_rewind(lfs1_t *lfs1, lfs1_dir_t *dir); + + +/// Miscellaneous littlefs specific operations /// + +// Traverse through all blocks in use by the filesystem +// +// The provided callback will be called with each block address that is +// currently in use by the filesystem. This can be used to determine which +// blocks are in use or how much of the storage is available. +// +// Returns a negative error code on failure. +int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data); + +// Prunes any recoverable errors that may have occured in the filesystem +// +// Not needed to be called by user unless an operation is interrupted +// but the filesystem is still mounted. This is already called on first +// allocation. +// +// Returns a negative error code on failure. +int lfs1_deorphan(lfs1_t *lfs1); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/lib/littlefs/lfs1_util.c b/lib/littlefs/lfs1_util.c new file mode 100644 index 0000000000000..3832a5ddb35a6 --- /dev/null +++ b/lib/littlefs/lfs1_util.c @@ -0,0 +1,31 @@ +/* + * lfs1 util functions + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "lfs1_util.h" + +// Only compile if user does not provide custom config +#ifndef LFS1_CONFIG + + +// Software CRC implementation with small lookup table +void lfs1_crc(uint32_t *restrict crc, const void *buffer, size_t size) { + static const uint32_t rtable[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c, + }; + + const uint8_t *data = buffer; + + for (size_t i = 0; i < size; i++) { + *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf]; + *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf]; + } +} + + +#endif diff --git a/lib/littlefs/lfs1_util.h b/lib/littlefs/lfs1_util.h new file mode 100644 index 0000000000000..b33b6a7adcff2 --- /dev/null +++ b/lib/littlefs/lfs1_util.h @@ -0,0 +1,186 @@ +/* + * lfs1 utility functions + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LFS1_UTIL_H +#define LFS1_UTIL_H + +// Users can override lfs1_util.h with their own configuration by defining +// LFS1_CONFIG as a header file to include (-DLFS1_CONFIG=lfs1_config.h). +// +// If LFS1_CONFIG is used, none of the default utils will be emitted and must be +// provided by the config file. To start I would suggest copying lfs1_util.h and +// modifying as needed. +#ifdef LFS1_CONFIG +#define LFS1_STRINGIZE(x) LFS1_STRINGIZE2(x) +#define LFS1_STRINGIZE2(x) #x +#include LFS1_STRINGIZE(LFS1_CONFIG) +#else + +// System includes +#include +#include +#include + +#ifndef LFS1_NO_MALLOC +#include +#endif +#ifndef LFS1_NO_ASSERT +#include +#endif +#if !defined(LFS1_NO_DEBUG) || !defined(LFS1_NO_WARN) || !defined(LFS1_NO_ERROR) +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + + +// Macros, may be replaced by system specific wrappers. Arguments to these +// macros must not have side-effects as the macros can be removed for a smaller +// code footprint + +// Logging functions +#ifndef LFS1_NO_DEBUG +#define LFS1_DEBUG(fmt, ...) \ + printf("lfs1 debug:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS1_DEBUG(fmt, ...) +#endif + +#ifndef LFS1_NO_WARN +#define LFS1_WARN(fmt, ...) \ + printf("lfs1 warn:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS1_WARN(fmt, ...) +#endif + +#ifndef LFS1_NO_ERROR +#define LFS1_ERROR(fmt, ...) \ + printf("lfs1 error:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS1_ERROR(fmt, ...) +#endif + +// Runtime assertions +#ifndef LFS1_NO_ASSERT +#define LFS1_ASSERT(test) assert(test) +#else +#define LFS1_ASSERT(test) +#endif + + +// Builtin functions, these may be replaced by more efficient +// toolchain-specific implementations. LFS1_NO_INTRINSICS falls back to a more +// expensive basic C implementation for debugging purposes + +// Min/max functions for unsigned 32-bit numbers +static inline uint32_t lfs1_max(uint32_t a, uint32_t b) { + return (a > b) ? a : b; +} + +static inline uint32_t lfs1_min(uint32_t a, uint32_t b) { + return (a < b) ? a : b; +} + +// Find the next smallest power of 2 less than or equal to a +static inline uint32_t lfs1_npw2(uint32_t a) { +#if !defined(LFS1_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return 32 - __builtin_clz(a-1); +#else + uint32_t r = 0; + uint32_t s; + a -= 1; + s = (a > 0xffff) << 4; a >>= s; r |= s; + s = (a > 0xff ) << 3; a >>= s; r |= s; + s = (a > 0xf ) << 2; a >>= s; r |= s; + s = (a > 0x3 ) << 1; a >>= s; r |= s; + return (r | (a >> 1)) + 1; +#endif +} + +// Count the number of trailing binary zeros in a +// lfs1_ctz(0) may be undefined +static inline uint32_t lfs1_ctz(uint32_t a) { +#if !defined(LFS1_NO_INTRINSICS) && defined(__GNUC__) + return __builtin_ctz(a); +#else + return lfs1_npw2((a & -a) + 1) - 1; +#endif +} + +// Count the number of binary ones in a +static inline uint32_t lfs1_popc(uint32_t a) { +#if !defined(LFS1_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return __builtin_popcount(a); +#else + a = a - ((a >> 1) & 0x55555555); + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); + return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; +#endif +} + +// Find the sequence comparison of a and b, this is the distance +// between a and b ignoring overflow +static inline int lfs1_scmp(uint32_t a, uint32_t b) { + return (int)(unsigned)(a - b); +} + +// Convert from 32-bit little-endian to native order +static inline uint32_t lfs1_fromle32(uint32_t a) { +#if !defined(LFS1_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + return a; +#elif !defined(LFS1_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + return __builtin_bswap32(a); +#else + return (((uint8_t*)&a)[0] << 0) | + (((uint8_t*)&a)[1] << 8) | + (((uint8_t*)&a)[2] << 16) | + (((uint8_t*)&a)[3] << 24); +#endif +} + +// Convert to 32-bit little-endian from native order +static inline uint32_t lfs1_tole32(uint32_t a) { + return lfs1_fromle32(a); +} + +// Calculate CRC-32 with polynomial = 0x04c11db7 +void lfs1_crc(uint32_t *crc, const void *buffer, size_t size); + +// Allocate memory, only used if buffers are not provided to littlefs +static inline void *lfs1_malloc(size_t size) { +#ifndef LFS1_NO_MALLOC + return malloc(size); +#else + (void)size; + return NULL; +#endif +} + +// Deallocate memory, only used if buffers are not provided to littlefs +static inline void lfs1_free(void *p) { +#ifndef LFS1_NO_MALLOC + free(p); +#else + (void)p; +#endif +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif +#endif From 2e66d83ca445d5b7216c1e483bd51bc5e6127ddc Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 17:23:23 +1100 Subject: [PATCH 0629/1299] lib/littlefs: Add littlefs v2.1.3 source. --- lib/littlefs/lfs2.c | 4742 ++++++++++++++++++++++++++++++++++++++ lib/littlefs/lfs2.h | 651 ++++++ lib/littlefs/lfs2_util.c | 33 + lib/littlefs/lfs2_util.h | 230 ++ 4 files changed, 5656 insertions(+) create mode 100644 lib/littlefs/lfs2.c create mode 100644 lib/littlefs/lfs2.h create mode 100644 lib/littlefs/lfs2_util.c create mode 100644 lib/littlefs/lfs2_util.h diff --git a/lib/littlefs/lfs2.c b/lib/littlefs/lfs2.c new file mode 100644 index 0000000000000..dea01b1c07fbb --- /dev/null +++ b/lib/littlefs/lfs2.c @@ -0,0 +1,4742 @@ +/* + * The little filesystem + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "lfs2.h" +#include "lfs2_util.h" + +#define LFS2_BLOCK_NULL ((lfs2_block_t)-1) +#define LFS2_BLOCK_INLINE ((lfs2_block_t)-2) + +/// Caching block device operations /// +static inline void lfs2_cache_drop(lfs2_t *lfs2, lfs2_cache_t *rcache) { + // do not zero, cheaper if cache is readonly or only going to be + // written with identical data (during relocates) + (void)lfs2; + rcache->block = LFS2_BLOCK_NULL; +} + +static inline void lfs2_cache_zero(lfs2_t *lfs2, lfs2_cache_t *pcache) { + // zero to avoid information leak + memset(pcache->buffer, 0xff, lfs2->cfg->cache_size); + pcache->block = LFS2_BLOCK_NULL; +} + +static int lfs2_bd_read(lfs2_t *lfs2, + const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint, + lfs2_block_t block, lfs2_off_t off, + void *buffer, lfs2_size_t size) { + uint8_t *data = buffer; + LFS2_ASSERT(block != LFS2_BLOCK_NULL); + if (off+size > lfs2->cfg->block_size) { + return LFS2_ERR_CORRUPT; + } + + while (size > 0) { + lfs2_size_t diff = size; + + if (pcache && block == pcache->block && + off < pcache->off + pcache->size) { + if (off >= pcache->off) { + // is already in pcache? + diff = lfs2_min(diff, pcache->size - (off-pcache->off)); + memcpy(data, &pcache->buffer[off-pcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + // pcache takes priority + diff = lfs2_min(diff, pcache->off-off); + } + + if (block == rcache->block && + off < rcache->off + rcache->size) { + if (off >= rcache->off) { + // is already in rcache? + diff = lfs2_min(diff, rcache->size - (off-rcache->off)); + memcpy(data, &rcache->buffer[off-rcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + // rcache takes priority + diff = lfs2_min(diff, rcache->off-off); + } + + // load to cache, first condition can no longer fail + LFS2_ASSERT(block < lfs2->cfg->block_count); + rcache->block = block; + rcache->off = lfs2_aligndown(off, lfs2->cfg->read_size); + rcache->size = lfs2_min( + lfs2_min( + lfs2_alignup(off+hint, lfs2->cfg->read_size), + lfs2->cfg->block_size) + - rcache->off, + lfs2->cfg->cache_size); + int err = lfs2->cfg->read(lfs2->cfg, rcache->block, + rcache->off, rcache->buffer, rcache->size); + LFS2_ASSERT(err <= 0); + if (err) { + return err; + } + } + + return 0; +} + +enum { + LFS2_CMP_EQ = 0, + LFS2_CMP_LT = 1, + LFS2_CMP_GT = 2, +}; + +static int lfs2_bd_cmp(lfs2_t *lfs2, + const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint, + lfs2_block_t block, lfs2_off_t off, + const void *buffer, lfs2_size_t size) { + const uint8_t *data = buffer; + + for (lfs2_off_t i = 0; i < size; i++) { + uint8_t dat; + int err = lfs2_bd_read(lfs2, + pcache, rcache, hint-i, + block, off+i, &dat, 1); + if (err) { + return err; + } + + if (dat != data[i]) { + return (dat < data[i]) ? LFS2_CMP_LT : LFS2_CMP_GT; + } + } + + return LFS2_CMP_EQ; +} + +static int lfs2_bd_flush(lfs2_t *lfs2, + lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) { + if (pcache->block != LFS2_BLOCK_NULL && pcache->block != LFS2_BLOCK_INLINE) { + LFS2_ASSERT(pcache->block < lfs2->cfg->block_count); + lfs2_size_t diff = lfs2_alignup(pcache->size, lfs2->cfg->prog_size); + int err = lfs2->cfg->prog(lfs2->cfg, pcache->block, + pcache->off, pcache->buffer, diff); + LFS2_ASSERT(err <= 0); + if (err) { + return err; + } + + if (validate) { + // check data on disk + lfs2_cache_drop(lfs2, rcache); + int res = lfs2_bd_cmp(lfs2, + NULL, rcache, diff, + pcache->block, pcache->off, pcache->buffer, diff); + if (res < 0) { + return res; + } + + if (res != LFS2_CMP_EQ) { + return LFS2_ERR_CORRUPT; + } + } + + lfs2_cache_zero(lfs2, pcache); + } + + return 0; +} + +static int lfs2_bd_sync(lfs2_t *lfs2, + lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) { + lfs2_cache_drop(lfs2, rcache); + + int err = lfs2_bd_flush(lfs2, pcache, rcache, validate); + if (err) { + return err; + } + + err = lfs2->cfg->sync(lfs2->cfg); + LFS2_ASSERT(err <= 0); + return err; +} + +static int lfs2_bd_prog(lfs2_t *lfs2, + lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate, + lfs2_block_t block, lfs2_off_t off, + const void *buffer, lfs2_size_t size) { + const uint8_t *data = buffer; + LFS2_ASSERT(block != LFS2_BLOCK_NULL); + LFS2_ASSERT(off + size <= lfs2->cfg->block_size); + + while (size > 0) { + if (block == pcache->block && + off >= pcache->off && + off < pcache->off + lfs2->cfg->cache_size) { + // already fits in pcache? + lfs2_size_t diff = lfs2_min(size, + lfs2->cfg->cache_size - (off-pcache->off)); + memcpy(&pcache->buffer[off-pcache->off], data, diff); + + data += diff; + off += diff; + size -= diff; + + pcache->size = lfs2_max(pcache->size, off - pcache->off); + if (pcache->size == lfs2->cfg->cache_size) { + // eagerly flush out pcache if we fill up + int err = lfs2_bd_flush(lfs2, pcache, rcache, validate); + if (err) { + return err; + } + } + + continue; + } + + // pcache must have been flushed, either by programming and + // entire block or manually flushing the pcache + LFS2_ASSERT(pcache->block == LFS2_BLOCK_NULL); + + // prepare pcache, first condition can no longer fail + pcache->block = block; + pcache->off = lfs2_aligndown(off, lfs2->cfg->prog_size); + pcache->size = 0; + } + + return 0; +} + +static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) { + LFS2_ASSERT(block < lfs2->cfg->block_count); + int err = lfs2->cfg->erase(lfs2->cfg, block); + LFS2_ASSERT(err <= 0); + return err; +} + + +/// Small type-level utilities /// +// operations on block pairs +static inline void lfs2_pair_swap(lfs2_block_t pair[2]) { + lfs2_block_t t = pair[0]; + pair[0] = pair[1]; + pair[1] = t; +} + +static inline bool lfs2_pair_isnull(const lfs2_block_t pair[2]) { + return pair[0] == LFS2_BLOCK_NULL || pair[1] == LFS2_BLOCK_NULL; +} + +static inline int lfs2_pair_cmp( + const lfs2_block_t paira[2], + const lfs2_block_t pairb[2]) { + return !(paira[0] == pairb[0] || paira[1] == pairb[1] || + paira[0] == pairb[1] || paira[1] == pairb[0]); +} + +static inline bool lfs2_pair_sync( + const lfs2_block_t paira[2], + const lfs2_block_t pairb[2]) { + return (paira[0] == pairb[0] && paira[1] == pairb[1]) || + (paira[0] == pairb[1] && paira[1] == pairb[0]); +} + +static inline void lfs2_pair_fromle32(lfs2_block_t pair[2]) { + pair[0] = lfs2_fromle32(pair[0]); + pair[1] = lfs2_fromle32(pair[1]); +} + +static inline void lfs2_pair_tole32(lfs2_block_t pair[2]) { + pair[0] = lfs2_tole32(pair[0]); + pair[1] = lfs2_tole32(pair[1]); +} + +// operations on 32-bit entry tags +typedef uint32_t lfs2_tag_t; +typedef int32_t lfs2_stag_t; + +#define LFS2_MKTAG(type, id, size) \ + (((lfs2_tag_t)(type) << 20) | ((lfs2_tag_t)(id) << 10) | (lfs2_tag_t)(size)) + +static inline bool lfs2_tag_isvalid(lfs2_tag_t tag) { + return !(tag & 0x80000000); +} + +static inline bool lfs2_tag_isdelete(lfs2_tag_t tag) { + return ((int32_t)(tag << 22) >> 22) == -1; +} + +static inline uint16_t lfs2_tag_type1(lfs2_tag_t tag) { + return (tag & 0x70000000) >> 20; +} + +static inline uint16_t lfs2_tag_type3(lfs2_tag_t tag) { + return (tag & 0x7ff00000) >> 20; +} + +static inline uint8_t lfs2_tag_chunk(lfs2_tag_t tag) { + return (tag & 0x0ff00000) >> 20; +} + +static inline int8_t lfs2_tag_splice(lfs2_tag_t tag) { + return (int8_t)lfs2_tag_chunk(tag); +} + +static inline uint16_t lfs2_tag_id(lfs2_tag_t tag) { + return (tag & 0x000ffc00) >> 10; +} + +static inline lfs2_size_t lfs2_tag_size(lfs2_tag_t tag) { + return tag & 0x000003ff; +} + +static inline lfs2_size_t lfs2_tag_dsize(lfs2_tag_t tag) { + return sizeof(tag) + lfs2_tag_size(tag + lfs2_tag_isdelete(tag)); +} + +// operations on attributes in attribute lists +struct lfs2_mattr { + lfs2_tag_t tag; + const void *buffer; +}; + +struct lfs2_diskoff { + lfs2_block_t block; + lfs2_off_t off; +}; + +#define LFS2_MKATTRS(...) \ + (struct lfs2_mattr[]){__VA_ARGS__}, \ + sizeof((struct lfs2_mattr[]){__VA_ARGS__}) / sizeof(struct lfs2_mattr) + +// operations on global state +static inline void lfs2_gstate_xor(struct lfs2_gstate *a, + const struct lfs2_gstate *b) { + for (int i = 0; i < 3; i++) { + ((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i]; + } +} + +static inline bool lfs2_gstate_iszero(const struct lfs2_gstate *a) { + for (int i = 0; i < 3; i++) { + if (((uint32_t*)a)[i] != 0) { + return false; + } + } + return true; +} + +static inline bool lfs2_gstate_hasorphans(const struct lfs2_gstate *a) { + return lfs2_tag_size(a->tag); +} + +static inline uint8_t lfs2_gstate_getorphans(const struct lfs2_gstate *a) { + return lfs2_tag_size(a->tag); +} + +static inline bool lfs2_gstate_hasmove(const struct lfs2_gstate *a) { + return lfs2_tag_type1(a->tag); +} + +static inline bool lfs2_gstate_hasmovehere(const struct lfs2_gstate *a, + const lfs2_block_t *pair) { + return lfs2_tag_type1(a->tag) && lfs2_pair_cmp(a->pair, pair) == 0; +} + +static inline void lfs2_gstate_xororphans(struct lfs2_gstate *a, + const struct lfs2_gstate *b, bool orphans) { + a->tag ^= LFS2_MKTAG(0x800, 0, 0) & (b->tag ^ ((uint32_t)orphans << 31)); +} + +static inline void lfs2_gstate_xormove(struct lfs2_gstate *a, + const struct lfs2_gstate *b, uint16_t id, const lfs2_block_t pair[2]) { + a->tag ^= LFS2_MKTAG(0x7ff, 0x3ff, 0) & (b->tag ^ ( + (id != 0x3ff) ? LFS2_MKTAG(LFS2_TYPE_DELETE, id, 0) : 0)); + a->pair[0] ^= b->pair[0] ^ ((id != 0x3ff) ? pair[0] : 0); + a->pair[1] ^= b->pair[1] ^ ((id != 0x3ff) ? pair[1] : 0); +} + +static inline void lfs2_gstate_fromle32(struct lfs2_gstate *a) { + a->tag = lfs2_fromle32(a->tag); + a->pair[0] = lfs2_fromle32(a->pair[0]); + a->pair[1] = lfs2_fromle32(a->pair[1]); +} + +static inline void lfs2_gstate_tole32(struct lfs2_gstate *a) { + a->tag = lfs2_tole32(a->tag); + a->pair[0] = lfs2_tole32(a->pair[0]); + a->pair[1] = lfs2_tole32(a->pair[1]); +} + +// other endianness operations +static void lfs2_ctz_fromle32(struct lfs2_ctz *ctz) { + ctz->head = lfs2_fromle32(ctz->head); + ctz->size = lfs2_fromle32(ctz->size); +} + +static void lfs2_ctz_tole32(struct lfs2_ctz *ctz) { + ctz->head = lfs2_tole32(ctz->head); + ctz->size = lfs2_tole32(ctz->size); +} + +static inline void lfs2_superblock_fromle32(lfs2_superblock_t *superblock) { + superblock->version = lfs2_fromle32(superblock->version); + superblock->block_size = lfs2_fromle32(superblock->block_size); + superblock->block_count = lfs2_fromle32(superblock->block_count); + superblock->name_max = lfs2_fromle32(superblock->name_max); + superblock->file_max = lfs2_fromle32(superblock->file_max); + superblock->attr_max = lfs2_fromle32(superblock->attr_max); +} + +static inline void lfs2_superblock_tole32(lfs2_superblock_t *superblock) { + superblock->version = lfs2_tole32(superblock->version); + superblock->block_size = lfs2_tole32(superblock->block_size); + superblock->block_count = lfs2_tole32(superblock->block_count); + superblock->name_max = lfs2_tole32(superblock->name_max); + superblock->file_max = lfs2_tole32(superblock->file_max); + superblock->attr_max = lfs2_tole32(superblock->attr_max); +} + + +/// Internal operations predeclared here /// +static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir, + const struct lfs2_mattr *attrs, int attrcount); +static int lfs2_dir_compact(lfs2_t *lfs2, + lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount, + lfs2_mdir_t *source, uint16_t begin, uint16_t end); +static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file); +static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file); +static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans); +static void lfs2_fs_prepmove(lfs2_t *lfs2, + uint16_t id, const lfs2_block_t pair[2]); +static int lfs2_fs_pred(lfs2_t *lfs2, const lfs2_block_t dir[2], + lfs2_mdir_t *pdir); +static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t dir[2], + lfs2_mdir_t *parent); +static int lfs2_fs_relocate(lfs2_t *lfs2, + const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]); +static int lfs2_fs_forceconsistency(lfs2_t *lfs2); +static int lfs2_deinit(lfs2_t *lfs2); +#ifdef LFS2_MIGRATE +static int lfs21_traverse(lfs2_t *lfs2, + int (*cb)(void*, lfs2_block_t), void *data); +#endif + +/// Block allocator /// +static int lfs2_alloc_lookahead(void *p, lfs2_block_t block) { + lfs2_t *lfs2 = (lfs2_t*)p; + lfs2_block_t off = ((block - lfs2->free.off) + + lfs2->cfg->block_count) % lfs2->cfg->block_count; + + if (off < lfs2->free.size) { + lfs2->free.buffer[off / 32] |= 1U << (off % 32); + } + + return 0; +} + +static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) { + while (true) { + while (lfs2->free.i != lfs2->free.size) { + lfs2_block_t off = lfs2->free.i; + lfs2->free.i += 1; + lfs2->free.ack -= 1; + + if (!(lfs2->free.buffer[off / 32] & (1U << (off % 32)))) { + // found a free block + *block = (lfs2->free.off + off) % lfs2->cfg->block_count; + + // eagerly find next off so an alloc ack can + // discredit old lookahead blocks + while (lfs2->free.i != lfs2->free.size && + (lfs2->free.buffer[lfs2->free.i / 32] + & (1U << (lfs2->free.i % 32)))) { + lfs2->free.i += 1; + lfs2->free.ack -= 1; + } + + return 0; + } + } + + // check if we have looked at all blocks since last ack + if (lfs2->free.ack == 0) { + LFS2_ERROR("No more free space %"PRIu32, + lfs2->free.i + lfs2->free.off); + return LFS2_ERR_NOSPC; + } + + lfs2->free.off = (lfs2->free.off + lfs2->free.size) + % lfs2->cfg->block_count; + lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->free.ack); + lfs2->free.i = 0; + + // find mask of free blocks from tree + memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); + int err = lfs2_fs_traverse(lfs2, lfs2_alloc_lookahead, lfs2); + if (err) { + return err; + } + } +} + +static void lfs2_alloc_ack(lfs2_t *lfs2) { + lfs2->free.ack = lfs2->cfg->block_count; +} + + +/// Metadata pair and directory operations /// +static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, + lfs2_tag_t gmask, lfs2_tag_t gtag, + lfs2_off_t goff, void *gbuffer, lfs2_size_t gsize) { + lfs2_off_t off = dir->off; + lfs2_tag_t ntag = dir->etag; + lfs2_stag_t gdiff = 0; + + if (lfs2_gstate_hasmovehere(&lfs2->gstate, dir->pair) && + lfs2_tag_id(gtag) <= lfs2_tag_id(lfs2->gstate.tag)) { + // synthetic moves + gdiff -= LFS2_MKTAG(0, 1, 0); + } + + // iterate over dir block backwards (for faster lookups) + while (off >= sizeof(lfs2_tag_t) + lfs2_tag_dsize(ntag)) { + off -= lfs2_tag_dsize(ntag); + lfs2_tag_t tag = ntag; + int err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, sizeof(ntag), + dir->pair[0], off, &ntag, sizeof(ntag)); + if (err) { + return err; + } + + ntag = (lfs2_frombe32(ntag) ^ tag) & 0x7fffffff; + + if (lfs2_tag_id(gmask) != 0 && + lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE && + lfs2_tag_id(tag) <= lfs2_tag_id(gtag - gdiff)) { + if (tag == (LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0) | + (LFS2_MKTAG(0, 0x3ff, 0) & (gtag - gdiff)))) { + // found where we were created + return LFS2_ERR_NOENT; + } + + // move around splices + gdiff += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0); + } + + if ((gmask & tag) == (gmask & (gtag - gdiff))) { + if (lfs2_tag_isdelete(tag)) { + return LFS2_ERR_NOENT; + } + + lfs2_size_t diff = lfs2_min(lfs2_tag_size(tag), gsize); + err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, diff, + dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff); + if (err) { + return err; + } + + memset((uint8_t*)gbuffer + diff, 0, gsize - diff); + + return tag + gdiff; + } + } + + return LFS2_ERR_NOENT; +} + +static lfs2_stag_t lfs2_dir_get(lfs2_t *lfs2, const lfs2_mdir_t *dir, + lfs2_tag_t gmask, lfs2_tag_t gtag, void *buffer) { + return lfs2_dir_getslice(lfs2, dir, + gmask, gtag, + 0, buffer, lfs2_tag_size(gtag)); +} + +static int lfs2_dir_getread(lfs2_t *lfs2, const lfs2_mdir_t *dir, + const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint, + lfs2_tag_t gmask, lfs2_tag_t gtag, + lfs2_off_t off, void *buffer, lfs2_size_t size) { + uint8_t *data = buffer; + if (off+size > lfs2->cfg->block_size) { + return LFS2_ERR_CORRUPT; + } + + while (size > 0) { + lfs2_size_t diff = size; + + if (pcache && pcache->block == LFS2_BLOCK_INLINE && + off < pcache->off + pcache->size) { + if (off >= pcache->off) { + // is already in pcache? + diff = lfs2_min(diff, pcache->size - (off-pcache->off)); + memcpy(data, &pcache->buffer[off-pcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + // pcache takes priority + diff = lfs2_min(diff, pcache->off-off); + } + + if (rcache->block == LFS2_BLOCK_INLINE && + off < rcache->off + rcache->size) { + if (off >= rcache->off) { + // is already in rcache? + diff = lfs2_min(diff, rcache->size - (off-rcache->off)); + memcpy(data, &rcache->buffer[off-rcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + // rcache takes priority + diff = lfs2_min(diff, rcache->off-off); + } + + // load to cache, first condition can no longer fail + rcache->block = LFS2_BLOCK_INLINE; + rcache->off = lfs2_aligndown(off, lfs2->cfg->read_size); + rcache->size = lfs2_min(lfs2_alignup(off+hint, lfs2->cfg->read_size), + lfs2->cfg->cache_size); + int err = lfs2_dir_getslice(lfs2, dir, gmask, gtag, + rcache->off, rcache->buffer, rcache->size); + if (err < 0) { + return err; + } + } + + return 0; +} + +static int lfs2_dir_traverse_filter(void *p, + lfs2_tag_t tag, const void *buffer) { + lfs2_tag_t *filtertag = p; + (void)buffer; + + // which mask depends on unique bit in tag structure + uint32_t mask = (tag & LFS2_MKTAG(0x100, 0, 0)) + ? LFS2_MKTAG(0x7ff, 0x3ff, 0) + : LFS2_MKTAG(0x700, 0x3ff, 0); + + // check for redundancy + if ((mask & tag) == (mask & *filtertag) || + lfs2_tag_isdelete(*filtertag) || + (LFS2_MKTAG(0x7ff, 0x3ff, 0) & tag) == ( + LFS2_MKTAG(LFS2_TYPE_DELETE, 0, 0) | + (LFS2_MKTAG(0, 0x3ff, 0) & *filtertag))) { + return true; + } + + // check if we need to adjust for created/deleted tags + if (lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE && + lfs2_tag_id(tag) <= lfs2_tag_id(*filtertag)) { + *filtertag += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0); + } + + return false; +} + +static int lfs2_dir_traverse(lfs2_t *lfs2, + const lfs2_mdir_t *dir, lfs2_off_t off, lfs2_tag_t ptag, + const struct lfs2_mattr *attrs, int attrcount, bool hasseenmove, + lfs2_tag_t tmask, lfs2_tag_t ttag, + uint16_t begin, uint16_t end, int16_t diff, + int (*cb)(void *data, lfs2_tag_t tag, const void *buffer), void *data) { + // iterate over directory and attrs + while (true) { + lfs2_tag_t tag; + const void *buffer; + struct lfs2_diskoff disk; + if (off+lfs2_tag_dsize(ptag) < dir->off) { + off += lfs2_tag_dsize(ptag); + int err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, sizeof(tag), + dir->pair[0], off, &tag, sizeof(tag)); + if (err) { + return err; + } + + tag = (lfs2_frombe32(tag) ^ ptag) | 0x80000000; + disk.block = dir->pair[0]; + disk.off = off+sizeof(lfs2_tag_t); + buffer = &disk; + ptag = tag; + } else if (attrcount > 0) { + tag = attrs[0].tag; + buffer = attrs[0].buffer; + attrs += 1; + attrcount -= 1; + } else if (!hasseenmove && + lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { + // Wait, we have pending move? Handle this here (we need to + // or else we risk letting moves fall out of date) + tag = lfs2->gpending.tag & LFS2_MKTAG(0x7ff, 0x3ff, 0); + buffer = NULL; + hasseenmove = true; + } else { + return 0; + } + + lfs2_tag_t mask = LFS2_MKTAG(0x7ff, 0, 0); + if ((mask & tmask & tag) != (mask & tmask & ttag)) { + continue; + } + + // do we need to filter? inlining the filtering logic here allows + // for some minor optimizations + if (lfs2_tag_id(tmask) != 0) { + // scan for duplicates and update tag based on creates/deletes + int filter = lfs2_dir_traverse(lfs2, + dir, off, ptag, attrs, attrcount, hasseenmove, + 0, 0, 0, 0, 0, + lfs2_dir_traverse_filter, &tag); + if (filter < 0) { + return filter; + } + + if (filter) { + continue; + } + + // in filter range? + if (!(lfs2_tag_id(tag) >= begin && lfs2_tag_id(tag) < end)) { + continue; + } + } + + // handle special cases for mcu-side operations + if (lfs2_tag_type3(tag) == LFS2_FROM_NOOP) { + // do nothing + } else if (lfs2_tag_type3(tag) == LFS2_FROM_MOVE) { + uint16_t fromid = lfs2_tag_size(tag); + uint16_t toid = lfs2_tag_id(tag); + int err = lfs2_dir_traverse(lfs2, + buffer, 0, LFS2_BLOCK_NULL, NULL, 0, true, + LFS2_MKTAG(0x600, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, 0, 0), + fromid, fromid+1, toid-fromid+diff, + cb, data); + if (err) { + return err; + } + } else if (lfs2_tag_type3(tag) == LFS2_FROM_USERATTRS) { + for (unsigned i = 0; i < lfs2_tag_size(tag); i++) { + const struct lfs2_attr *a = buffer; + int err = cb(data, LFS2_MKTAG(LFS2_TYPE_USERATTR + a[i].type, + lfs2_tag_id(tag) + diff, a[i].size), a[i].buffer); + if (err) { + return err; + } + } + } else { + int err = cb(data, tag + LFS2_MKTAG(0, diff, 0), buffer); + if (err) { + return err; + } + } + } +} + +static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2, + lfs2_mdir_t *dir, const lfs2_block_t pair[2], + lfs2_tag_t fmask, lfs2_tag_t ftag, uint16_t *id, + int (*cb)(void *data, lfs2_tag_t tag, const void *buffer), void *data) { + // we can find tag very efficiently during a fetch, since we're already + // scanning the entire directory + lfs2_stag_t besttag = -1; + + // find the block with the most recent revision + uint32_t revs[2] = {0, 0}; + int r = 0; + for (int i = 0; i < 2; i++) { + int err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, sizeof(revs[i]), + pair[i], 0, &revs[i], sizeof(revs[i])); + revs[i] = lfs2_fromle32(revs[i]); + if (err && err != LFS2_ERR_CORRUPT) { + return err; + } + + if (err != LFS2_ERR_CORRUPT && + lfs2_scmp(revs[i], revs[(i+1)%2]) > 0) { + r = i; + } + } + + dir->pair[0] = pair[(r+0)%2]; + dir->pair[1] = pair[(r+1)%2]; + dir->rev = revs[(r+0)%2]; + dir->off = 0; // nonzero = found some commits + + // now scan tags to fetch the actual dir and find possible match + for (int i = 0; i < 2; i++) { + lfs2_off_t off = 0; + lfs2_tag_t ptag = LFS2_BLOCK_NULL; + + uint16_t tempcount = 0; + lfs2_block_t temptail[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; + bool tempsplit = false; + lfs2_stag_t tempbesttag = besttag; + + dir->rev = lfs2_tole32(dir->rev); + uint32_t crc = lfs2_crc(LFS2_BLOCK_NULL, &dir->rev, sizeof(dir->rev)); + dir->rev = lfs2_fromle32(dir->rev); + + while (true) { + // extract next tag + lfs2_tag_t tag; + off += lfs2_tag_dsize(ptag); + int err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, lfs2->cfg->block_size, + dir->pair[0], off, &tag, sizeof(tag)); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + // can't continue? + dir->erased = false; + break; + } + return err; + } + + crc = lfs2_crc(crc, &tag, sizeof(tag)); + tag = lfs2_frombe32(tag) ^ ptag; + + // next commit not yet programmed or we're not in valid range + if (!lfs2_tag_isvalid(tag) || + off + lfs2_tag_dsize(tag) > lfs2->cfg->block_size) { + dir->erased = (lfs2_tag_type1(ptag) == LFS2_TYPE_CRC && + dir->off % lfs2->cfg->prog_size == 0); + break; + } + + ptag = tag; + + if (lfs2_tag_type1(tag) == LFS2_TYPE_CRC) { + // check the crc attr + uint32_t dcrc; + err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, lfs2->cfg->block_size, + dir->pair[0], off+sizeof(tag), &dcrc, sizeof(dcrc)); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + dir->erased = false; + break; + } + return err; + } + dcrc = lfs2_fromle32(dcrc); + + if (crc != dcrc) { + dir->erased = false; + break; + } + + // reset the next bit if we need to + ptag ^= (lfs2_tag_t)(lfs2_tag_chunk(tag) & 1U) << 31; + + // toss our crc into the filesystem seed for + // pseudorandom numbers + lfs2->seed ^= crc; + + // update with what's found so far + besttag = tempbesttag; + dir->off = off + lfs2_tag_dsize(tag); + dir->etag = ptag; + dir->count = tempcount; + dir->tail[0] = temptail[0]; + dir->tail[1] = temptail[1]; + dir->split = tempsplit; + + // reset crc + crc = LFS2_BLOCK_NULL; + continue; + } + + // crc the entry first, hopefully leaving it in the cache + for (lfs2_off_t j = sizeof(tag); j < lfs2_tag_dsize(tag); j++) { + uint8_t dat; + err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, lfs2->cfg->block_size, + dir->pair[0], off+j, &dat, 1); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + dir->erased = false; + break; + } + return err; + } + + crc = lfs2_crc(crc, &dat, 1); + } + + // directory modification tags? + if (lfs2_tag_type1(tag) == LFS2_TYPE_NAME) { + // increase count of files if necessary + if (lfs2_tag_id(tag) >= tempcount) { + tempcount = lfs2_tag_id(tag) + 1; + } + } else if (lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE) { + tempcount += lfs2_tag_splice(tag); + + if (tag == (LFS2_MKTAG(LFS2_TYPE_DELETE, 0, 0) | + (LFS2_MKTAG(0, 0x3ff, 0) & tempbesttag))) { + tempbesttag |= 0x80000000; + } else if (tempbesttag != -1 && + lfs2_tag_id(tag) <= lfs2_tag_id(tempbesttag)) { + tempbesttag += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0); + } + } else if (lfs2_tag_type1(tag) == LFS2_TYPE_TAIL) { + tempsplit = (lfs2_tag_chunk(tag) & 1); + + err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, lfs2->cfg->block_size, + dir->pair[0], off+sizeof(tag), &temptail, 8); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + dir->erased = false; + break; + } + } + lfs2_pair_fromle32(temptail); + } + + // found a match for our fetcher? + if ((fmask & tag) == (fmask & ftag)) { + int res = cb(data, tag, &(struct lfs2_diskoff){ + dir->pair[0], off+sizeof(tag)}); + if (res < 0) { + if (res == LFS2_ERR_CORRUPT) { + dir->erased = false; + break; + } + return res; + } + + if (res == LFS2_CMP_EQ) { + // found a match + tempbesttag = tag; + } else if (res == LFS2_CMP_GT && + lfs2_tag_id(tag) <= lfs2_tag_id(tempbesttag)) { + // found a greater match, keep track to keep things sorted + tempbesttag = tag | 0x80000000; + } + } + } + + // consider what we have good enough + if (dir->off > 0) { + // synthetic move + if (lfs2_gstate_hasmovehere(&lfs2->gstate, dir->pair)) { + if (lfs2_tag_id(lfs2->gstate.tag) == lfs2_tag_id(besttag)) { + besttag |= 0x80000000; + } else if (besttag != -1 && + lfs2_tag_id(lfs2->gstate.tag) < lfs2_tag_id(besttag)) { + besttag -= LFS2_MKTAG(0, 1, 0); + } + } + + // found tag? or found best id? + if (id) { + *id = lfs2_min(lfs2_tag_id(besttag), dir->count); + } + + if (lfs2_tag_isvalid(besttag)) { + return besttag; + } else if (lfs2_tag_id(besttag) < dir->count) { + return LFS2_ERR_NOENT; + } else { + return 0; + } + } + + // failed, try the other block? + lfs2_pair_swap(dir->pair); + dir->rev = revs[(r+1)%2]; + } + + LFS2_ERROR("Corrupted dir pair at %"PRIx32" %"PRIx32, + dir->pair[0], dir->pair[1]); + return LFS2_ERR_CORRUPT; +} + +static int lfs2_dir_fetch(lfs2_t *lfs2, + lfs2_mdir_t *dir, const lfs2_block_t pair[2]) { + // note, mask=-1, tag=0 can never match a tag since this + // pattern has the invalid bit set + return (int)lfs2_dir_fetchmatch(lfs2, dir, pair, -1, 0, NULL, NULL, NULL); +} + +static int lfs2_dir_getgstate(lfs2_t *lfs2, const lfs2_mdir_t *dir, + struct lfs2_gstate *gstate) { + struct lfs2_gstate temp; + lfs2_stag_t res = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x7ff, 0, 0), + LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0, sizeof(temp)), &temp); + if (res < 0 && res != LFS2_ERR_NOENT) { + return res; + } + + if (res != LFS2_ERR_NOENT) { + // xor together to find resulting gstate + lfs2_gstate_fromle32(&temp); + lfs2_gstate_xor(gstate, &temp); + } + + return 0; +} + +static int lfs2_dir_getinfo(lfs2_t *lfs2, lfs2_mdir_t *dir, + uint16_t id, struct lfs2_info *info) { + if (id == 0x3ff) { + // special case for root + strcpy(info->name, "/"); + info->type = LFS2_TYPE_DIR; + return 0; + } + + lfs2_stag_t tag = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x780, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_NAME, id, lfs2->name_max+1), info->name); + if (tag < 0) { + return (int)tag; + } + + info->type = lfs2_tag_type3(tag); + + struct lfs2_ctz ctz; + tag = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, id, sizeof(ctz)), &ctz); + if (tag < 0) { + return (int)tag; + } + lfs2_ctz_fromle32(&ctz); + + if (lfs2_tag_type3(tag) == LFS2_TYPE_CTZSTRUCT) { + info->size = ctz.size; + } else if (lfs2_tag_type3(tag) == LFS2_TYPE_INLINESTRUCT) { + info->size = lfs2_tag_size(tag); + } + + return 0; +} + +struct lfs2_dir_find_match { + lfs2_t *lfs2; + const void *name; + lfs2_size_t size; +}; + +static int lfs2_dir_find_match(void *data, + lfs2_tag_t tag, const void *buffer) { + struct lfs2_dir_find_match *name = data; + lfs2_t *lfs2 = name->lfs2; + const struct lfs2_diskoff *disk = buffer; + + // compare with disk + lfs2_size_t diff = lfs2_min(name->size, lfs2_tag_size(tag)); + int res = lfs2_bd_cmp(lfs2, + NULL, &lfs2->rcache, diff, + disk->block, disk->off, name->name, diff); + if (res != LFS2_CMP_EQ) { + return res; + } + + // only equal if our size is still the same + if (name->size != lfs2_tag_size(tag)) { + return (name->size < lfs2_tag_size(tag)) ? LFS2_CMP_LT : LFS2_CMP_GT; + } + + // found a match! + return LFS2_CMP_EQ; +} + +static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, + const char **path, uint16_t *id) { + // we reduce path to a single name if we can find it + const char *name = *path; + if (id) { + *id = 0x3ff; + } + + // default to root dir + lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0); + dir->tail[0] = lfs2->root[0]; + dir->tail[1] = lfs2->root[1]; + + while (true) { +nextname: + // skip slashes + name += strspn(name, "/"); + lfs2_size_t namelen = strcspn(name, "/"); + + // skip '.' and root '..' + if ((namelen == 1 && memcmp(name, ".", 1) == 0) || + (namelen == 2 && memcmp(name, "..", 2) == 0)) { + name += namelen; + goto nextname; + } + + // skip if matched by '..' in name + const char *suffix = name + namelen; + lfs2_size_t sufflen; + int depth = 1; + while (true) { + suffix += strspn(suffix, "/"); + sufflen = strcspn(suffix, "/"); + if (sufflen == 0) { + break; + } + + if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { + depth -= 1; + if (depth == 0) { + name = suffix + sufflen; + goto nextname; + } + } else { + depth += 1; + } + + suffix += sufflen; + } + + // found path + if (name[0] == '\0') { + return tag; + } + + // update what we've found so far + *path = name; + + // only continue if we hit a directory + if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { + return LFS2_ERR_NOTDIR; + } + + // grab the entry data + if (lfs2_tag_id(tag) != 0x3ff) { + lfs2_stag_t res = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), dir->tail); + if (res < 0) { + return res; + } + lfs2_pair_fromle32(dir->tail); + } + + // find entry matching name + while (true) { + tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail, + LFS2_MKTAG(0x780, 0, 0), + LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen), + // are we last name? + (strchr(name, '/') == NULL) ? id : NULL, + lfs2_dir_find_match, &(struct lfs2_dir_find_match){ + lfs2, name, namelen}); + if (tag < 0) { + return tag; + } + + if (tag) { + break; + } + + if (!dir->split) { + return LFS2_ERR_NOENT; + } + } + + // to next name + name += namelen; + } +} + +// commit logic +struct lfs2_commit { + lfs2_block_t block; + lfs2_off_t off; + lfs2_tag_t ptag; + uint32_t crc; + + lfs2_off_t begin; + lfs2_off_t end; +}; + +static int lfs2_dir_commitprog(lfs2_t *lfs2, struct lfs2_commit *commit, + const void *buffer, lfs2_size_t size) { + int err = lfs2_bd_prog(lfs2, + &lfs2->pcache, &lfs2->rcache, false, + commit->block, commit->off , + (const uint8_t*)buffer, size); + if (err) { + return err; + } + + commit->crc = lfs2_crc(commit->crc, buffer, size); + commit->off += size; + return 0; +} + +static int lfs2_dir_commitattr(lfs2_t *lfs2, struct lfs2_commit *commit, + lfs2_tag_t tag, const void *buffer) { + // check if we fit + lfs2_size_t dsize = lfs2_tag_dsize(tag); + if (commit->off + dsize > commit->end) { + return LFS2_ERR_NOSPC; + } + + // write out tag + lfs2_tag_t ntag = lfs2_tobe32((tag & 0x7fffffff) ^ commit->ptag); + int err = lfs2_dir_commitprog(lfs2, commit, &ntag, sizeof(ntag)); + if (err) { + return err; + } + + if (!(tag & 0x80000000)) { + // from memory + err = lfs2_dir_commitprog(lfs2, commit, buffer, dsize-sizeof(tag)); + if (err) { + return err; + } + } else { + // from disk + const struct lfs2_diskoff *disk = buffer; + for (lfs2_off_t i = 0; i < dsize-sizeof(tag); i++) { + // rely on caching to make this efficient + uint8_t dat; + err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, dsize-sizeof(tag)-i, + disk->block, disk->off+i, &dat, 1); + if (err) { + return err; + } + + err = lfs2_dir_commitprog(lfs2, commit, &dat, 1); + if (err) { + return err; + } + } + } + + commit->ptag = tag & 0x7fffffff; + return 0; +} + +static int lfs2_dir_commitcrc(lfs2_t *lfs2, struct lfs2_commit *commit) { + // align to program units + const lfs2_off_t off1 = commit->off + sizeof(lfs2_tag_t); + const lfs2_off_t end = lfs2_alignup(off1 + sizeof(uint32_t), + lfs2->cfg->prog_size); + + // create crc tags to fill up remainder of commit, note that + // padding is not crcd, which lets fetches skip padding but + // makes committing a bit more complicated + while (commit->off < end) { + lfs2_off_t off = commit->off + sizeof(lfs2_tag_t); + lfs2_off_t noff = lfs2_min(end - off, 0x3fe) + off; + if (noff < end) { + noff = lfs2_min(noff, end - 2*sizeof(uint32_t)); + } + + // read erased state from next program unit + lfs2_tag_t tag = LFS2_BLOCK_NULL; + int err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, sizeof(tag), + commit->block, noff, &tag, sizeof(tag)); + if (err && err != LFS2_ERR_CORRUPT) { + return err; + } + + // build crc tag + bool reset = ~lfs2_frombe32(tag) >> 31; + tag = LFS2_MKTAG(LFS2_TYPE_CRC + reset, 0x3ff, noff - off); + + // write out crc + uint32_t footer[2]; + footer[0] = lfs2_tobe32(tag ^ commit->ptag); + commit->crc = lfs2_crc(commit->crc, &footer[0], sizeof(footer[0])); + footer[1] = lfs2_tole32(commit->crc); + err = lfs2_bd_prog(lfs2, + &lfs2->pcache, &lfs2->rcache, false, + commit->block, commit->off, &footer, sizeof(footer)); + if (err) { + return err; + } + + commit->off += sizeof(tag)+lfs2_tag_size(tag); + commit->ptag = tag ^ ((lfs2_tag_t)reset << 31); + commit->crc = LFS2_BLOCK_NULL; // reset crc for next "commit" + } + + // flush buffers + int err = lfs2_bd_sync(lfs2, &lfs2->pcache, &lfs2->rcache, false); + if (err) { + return err; + } + + // successful commit, check checksums to make sure + lfs2_off_t off = commit->begin; + lfs2_off_t noff = off1; + while (off < end) { + uint32_t crc = LFS2_BLOCK_NULL; + for (lfs2_off_t i = off; i < noff+sizeof(uint32_t); i++) { + // leave it up to caching to make this efficient + uint8_t dat; + err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, noff+sizeof(uint32_t)-i, + commit->block, i, &dat, 1); + if (err) { + return err; + } + + crc = lfs2_crc(crc, &dat, 1); + } + + // detected write error? + if (crc != 0) { + return LFS2_ERR_CORRUPT; + } + + // skip padding + off = lfs2_min(end - noff, 0x3fe) + noff; + if (off < end) { + off = lfs2_min(off, end - 2*sizeof(uint32_t)); + } + noff = off + sizeof(uint32_t); + } + + return 0; +} + +static int lfs2_dir_alloc(lfs2_t *lfs2, lfs2_mdir_t *dir) { + // allocate pair of dir blocks (backwards, so we write block 1 first) + for (int i = 0; i < 2; i++) { + int err = lfs2_alloc(lfs2, &dir->pair[(i+1)%2]); + if (err) { + return err; + } + } + + // rather than clobbering one of the blocks we just pretend + // the revision may be valid + int err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, sizeof(dir->rev), + dir->pair[0], 0, &dir->rev, sizeof(dir->rev)); + dir->rev = lfs2_fromle32(dir->rev); + if (err && err != LFS2_ERR_CORRUPT) { + return err; + } + + // make sure we don't immediately evict + dir->rev += dir->rev & 1; + + // set defaults + dir->off = sizeof(dir->rev); + dir->etag = LFS2_BLOCK_NULL; + dir->count = 0; + dir->tail[0] = LFS2_BLOCK_NULL; + dir->tail[1] = LFS2_BLOCK_NULL; + dir->erased = false; + dir->split = false; + + // don't write out yet, let caller take care of that + return 0; +} + +static int lfs2_dir_drop(lfs2_t *lfs2, lfs2_mdir_t *dir, lfs2_mdir_t *tail) { + // steal state + int err = lfs2_dir_getgstate(lfs2, tail, &lfs2->gdelta); + if (err) { + return err; + } + + // steal tail + lfs2_pair_tole32(tail->tail); + err = lfs2_dir_commit(lfs2, dir, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_TAIL + tail->split, 0x3ff, 8), tail->tail})); + lfs2_pair_fromle32(tail->tail); + if (err) { + return err; + } + + return 0; +} + +static int lfs2_dir_split(lfs2_t *lfs2, + lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount, + lfs2_mdir_t *source, uint16_t split, uint16_t end) { + // create tail directory + lfs2_mdir_t tail; + int err = lfs2_dir_alloc(lfs2, &tail); + if (err) { + return err; + } + + tail.split = dir->split; + tail.tail[0] = dir->tail[0]; + tail.tail[1] = dir->tail[1]; + + err = lfs2_dir_compact(lfs2, &tail, attrs, attrcount, source, split, end); + if (err) { + return err; + } + + dir->tail[0] = tail.pair[0]; + dir->tail[1] = tail.pair[1]; + dir->split = true; + + // update root if needed + if (lfs2_pair_cmp(dir->pair, lfs2->root) == 0 && split == 0) { + lfs2->root[0] = tail.pair[0]; + lfs2->root[1] = tail.pair[1]; + } + + return 0; +} + +static int lfs2_dir_commit_size(void *p, lfs2_tag_t tag, const void *buffer) { + lfs2_size_t *size = p; + (void)buffer; + + *size += lfs2_tag_dsize(tag); + return 0; +} + +struct lfs2_dir_commit_commit { + lfs2_t *lfs2; + struct lfs2_commit *commit; +}; + +static int lfs2_dir_commit_commit(void *p, lfs2_tag_t tag, const void *buffer) { + struct lfs2_dir_commit_commit *commit = p; + return lfs2_dir_commitattr(commit->lfs2, commit->commit, tag, buffer); +} + +static int lfs2_dir_compact(lfs2_t *lfs2, + lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount, + lfs2_mdir_t *source, uint16_t begin, uint16_t end) { + // save some state in case block is bad + const lfs2_block_t oldpair[2] = {dir->pair[1], dir->pair[0]}; + bool relocated = false; + bool exhausted = false; + + // should we split? + while (end - begin > 1) { + // find size + lfs2_size_t size = 0; + int err = lfs2_dir_traverse(lfs2, + source, 0, LFS2_BLOCK_NULL, attrs, attrcount, false, + LFS2_MKTAG(0x400, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_NAME, 0, 0), + begin, end, -begin, + lfs2_dir_commit_size, &size); + if (err) { + return err; + } + + // space is complicated, we need room for tail, crc, gstate, + // cleanup delete, and we cap at half a block to give room + // for metadata updates. + if (end - begin < 0xff && + size <= lfs2_min(lfs2->cfg->block_size - 36, + lfs2_alignup(lfs2->cfg->block_size/2, + lfs2->cfg->prog_size))) { + break; + } + + // can't fit, need to split, we should really be finding the + // largest size that fits with a small binary search, but right now + // it's not worth the code size + uint16_t split = (end - begin) / 2; + err = lfs2_dir_split(lfs2, dir, attrs, attrcount, + source, begin+split, end); + if (err) { + // if we fail to split, we may be able to overcompact, unless + // we're too big for even the full block, in which case our + // only option is to error + if (err == LFS2_ERR_NOSPC && size <= lfs2->cfg->block_size - 36) { + break; + } + return err; + } + + end = begin + split; + } + + // increment revision count + dir->rev += 1; + if (lfs2->cfg->block_cycles > 0 && + (dir->rev % (lfs2->cfg->block_cycles+1) == 0)) { + if (lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) { + // oh no! we're writing too much to the superblock, + // should we expand? + lfs2_ssize_t res = lfs2_fs_size(lfs2); + if (res < 0) { + return res; + } + + // do we have extra space? littlefs can't reclaim this space + // by itself, so expand cautiously + if ((lfs2_size_t)res < lfs2->cfg->block_count/2) { + LFS2_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev); + int err = lfs2_dir_split(lfs2, dir, attrs, attrcount, + source, begin, end); + if (err && err != LFS2_ERR_NOSPC) { + return err; + } + + // welp, we tried, if we ran out of space there's not much + // we can do, we'll error later if we've become frozen + if (!err) { + end = begin; + } + } +#ifdef LFS2_MIGRATE + } else if (lfs2_pair_cmp(dir->pair, lfs2->root) == 0 && lfs2->lfs21) { + // we can't relocate our root during migrations, as this would + // cause the superblock to get updated, which would clobber v1 +#endif + } else { + // we're writing too much, time to relocate + exhausted = true; + goto relocate; + } + } + + // begin loop to commit compaction to blocks until a compact sticks + while (true) { + { + // There's nothing special about our global delta, so feed it into + // our local global delta + int err = lfs2_dir_getgstate(lfs2, dir, &lfs2->gdelta); + if (err) { + return err; + } + + // setup commit state + struct lfs2_commit commit = { + .block = dir->pair[1], + .off = 0, + .ptag = LFS2_BLOCK_NULL, + .crc = LFS2_BLOCK_NULL, + + .begin = 0, + .end = lfs2->cfg->block_size - 8, + }; + + // erase block to write to + err = lfs2_bd_erase(lfs2, dir->pair[1]); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // write out header + dir->rev = lfs2_tole32(dir->rev); + err = lfs2_dir_commitprog(lfs2, &commit, + &dir->rev, sizeof(dir->rev)); + dir->rev = lfs2_fromle32(dir->rev); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // traverse the directory, this time writing out all unique tags + err = lfs2_dir_traverse(lfs2, + source, 0, LFS2_BLOCK_NULL, attrs, attrcount, false, + LFS2_MKTAG(0x400, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_NAME, 0, 0), + begin, end, -begin, + lfs2_dir_commit_commit, &(struct lfs2_dir_commit_commit){ + lfs2, &commit}); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // commit tail, which may be new after last size check + if (!lfs2_pair_isnull(dir->tail)) { + lfs2_pair_tole32(dir->tail); + err = lfs2_dir_commitattr(lfs2, &commit, + LFS2_MKTAG(LFS2_TYPE_TAIL + dir->split, 0x3ff, 8), + dir->tail); + lfs2_pair_fromle32(dir->tail); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + if (!relocated && !lfs2_gstate_iszero(&lfs2->gdelta)) { + // commit any globals, unless we're relocating, + // in which case our parent will steal our globals + lfs2_gstate_tole32(&lfs2->gdelta); + err = lfs2_dir_commitattr(lfs2, &commit, + LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0x3ff, + sizeof(lfs2->gdelta)), &lfs2->gdelta); + lfs2_gstate_fromle32(&lfs2->gdelta); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + err = lfs2_dir_commitcrc(lfs2, &commit); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // successful compaction, swap dir pair to indicate most recent + LFS2_ASSERT(commit.off % lfs2->cfg->prog_size == 0); + lfs2_pair_swap(dir->pair); + dir->count = end - begin; + dir->off = commit.off; + dir->etag = commit.ptag; + // note we able to have already handled move here + if (lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { + lfs2_gstate_xormove(&lfs2->gpending, + &lfs2->gpending, 0x3ff, NULL); + } + } + break; + +relocate: + // commit was corrupted, drop caches and prepare to relocate block + relocated = true; + lfs2_cache_drop(lfs2, &lfs2->pcache); + if (!exhausted) { + LFS2_DEBUG("Bad block at %"PRIx32, dir->pair[1]); + } + + // can't relocate superblock, filesystem is now frozen + if (lfs2_pair_cmp(oldpair, (const lfs2_block_t[2]){0, 1}) == 0) { + LFS2_WARN("Superblock %"PRIx32" has become unwritable", oldpair[1]); + return LFS2_ERR_NOSPC; + } + + // relocate half of pair + int err = lfs2_alloc(lfs2, &dir->pair[1]); + if (err && (err != LFS2_ERR_NOSPC && !exhausted)) { + return err; + } + + continue; + } + + if (!relocated) { + lfs2->gstate = lfs2->gpending; + lfs2->gdelta = (struct lfs2_gstate){0}; + } else { + // update references if we relocated + LFS2_DEBUG("Relocating %"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, + oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); + int err = lfs2_fs_relocate(lfs2, oldpair, dir->pair); + if (err) { + return err; + } + } + + return 0; +} + +static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir, + const struct lfs2_mattr *attrs, int attrcount) { + // check for any inline files that aren't RAM backed and + // forcefully evict them, needed for filesystem consistency + for (lfs2_file_t *f = (lfs2_file_t*)lfs2->mlist; f; f = f->next) { + if (dir != &f->m && lfs2_pair_cmp(f->m.pair, dir->pair) == 0 && + f->type == LFS2_TYPE_REG && (f->flags & LFS2_F_INLINE) && + f->ctz.size > lfs2->cfg->cache_size) { + int err = lfs2_file_outline(lfs2, f); + if (err) { + return err; + } + + err = lfs2_file_flush(lfs2, f); + if (err) { + return err; + } + } + } + + // calculate changes to the directory + lfs2_tag_t deletetag = LFS2_BLOCK_NULL; + lfs2_tag_t createtag = LFS2_BLOCK_NULL; + for (int i = 0; i < attrcount; i++) { + if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_CREATE) { + createtag = attrs[i].tag; + dir->count += 1; + } else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE) { + deletetag = attrs[i].tag; + LFS2_ASSERT(dir->count > 0); + dir->count -= 1; + } else if (lfs2_tag_type1(attrs[i].tag) == LFS2_TYPE_TAIL) { + dir->tail[0] = ((lfs2_block_t*)attrs[i].buffer)[0]; + dir->tail[1] = ((lfs2_block_t*)attrs[i].buffer)[1]; + dir->split = (lfs2_tag_chunk(attrs[i].tag) & 1); + lfs2_pair_fromle32(dir->tail); + } + } + + // do we have a pending move? + if (lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { + deletetag = lfs2->gpending.tag & LFS2_MKTAG(0x7ff, 0x3ff, 0); + LFS2_ASSERT(dir->count > 0); + dir->count -= 1; + + // mark gdelta so we reflect the move we will fix + lfs2_gstate_xormove(&lfs2->gdelta, &lfs2->gpending, 0x3ff, NULL); + } + + // should we actually drop the directory block? + if (lfs2_tag_isvalid(deletetag) && dir->count == 0) { + lfs2_mdir_t pdir; + int err = lfs2_fs_pred(lfs2, dir->pair, &pdir); + if (err && err != LFS2_ERR_NOENT) { + return err; + } + + if (err != LFS2_ERR_NOENT && pdir.split) { + return lfs2_dir_drop(lfs2, &pdir, dir); + } + } + + if (dir->erased || dir->count >= 0xff) { + // try to commit + struct lfs2_commit commit = { + .block = dir->pair[0], + .off = dir->off, + .ptag = dir->etag, + .crc = LFS2_BLOCK_NULL, + + .begin = dir->off, + .end = lfs2->cfg->block_size - 8, + }; + + // traverse attrs that need to be written out + lfs2_pair_tole32(dir->tail); + int err = lfs2_dir_traverse(lfs2, + dir, dir->off, dir->etag, attrs, attrcount, false, + 0, 0, 0, 0, 0, + lfs2_dir_commit_commit, &(struct lfs2_dir_commit_commit){ + lfs2, &commit}); + lfs2_pair_fromle32(dir->tail); + if (err) { + if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) { + goto compact; + } + return err; + } + + // commit any global diffs if we have any + if (!lfs2_gstate_iszero(&lfs2->gdelta)) { + err = lfs2_dir_getgstate(lfs2, dir, &lfs2->gdelta); + if (err) { + return err; + } + + lfs2_gstate_tole32(&lfs2->gdelta); + err = lfs2_dir_commitattr(lfs2, &commit, + LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0x3ff, + sizeof(lfs2->gdelta)), &lfs2->gdelta); + lfs2_gstate_fromle32(&lfs2->gdelta); + if (err) { + if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) { + goto compact; + } + return err; + } + } + + // finalize commit with the crc + err = lfs2_dir_commitcrc(lfs2, &commit); + if (err) { + if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) { + goto compact; + } + return err; + } + + // successful commit, update dir + LFS2_ASSERT(commit.off % lfs2->cfg->prog_size == 0); + dir->off = commit.off; + dir->etag = commit.ptag; + + // note we able to have already handled move here + if (lfs2_gstate_hasmovehere(&lfs2->gpending, dir->pair)) { + lfs2_gstate_xormove(&lfs2->gpending, &lfs2->gpending, 0x3ff, NULL); + } + + // update gstate + lfs2->gstate = lfs2->gpending; + lfs2->gdelta = (struct lfs2_gstate){0}; + } else { +compact: + // fall back to compaction + lfs2_cache_drop(lfs2, &lfs2->pcache); + + int err = lfs2_dir_compact(lfs2, dir, attrs, attrcount, + dir, 0, dir->count); + if (err) { + return err; + } + } + + // update any directories that are affected + lfs2_mdir_t copy = *dir; + + // two passes, once for things that aren't us, and one + // for things that are + for (struct lfs2_mlist *d = lfs2->mlist; d; d = d->next) { + if (lfs2_pair_cmp(d->m.pair, copy.pair) == 0) { + d->m = *dir; + if (d->id == lfs2_tag_id(deletetag)) { + d->m.pair[0] = LFS2_BLOCK_NULL; + d->m.pair[1] = LFS2_BLOCK_NULL; + } else if (d->id > lfs2_tag_id(deletetag)) { + d->id -= 1; + if (d->type == LFS2_TYPE_DIR) { + ((lfs2_dir_t*)d)->pos -= 1; + } + } else if (&d->m != dir && d->id >= lfs2_tag_id(createtag)) { + d->id += 1; + if (d->type == LFS2_TYPE_DIR) { + ((lfs2_dir_t*)d)->pos += 1; + } + } + + while (d->id >= d->m.count && d->m.split) { + // we split and id is on tail now + d->id -= d->m.count; + int err = lfs2_dir_fetch(lfs2, &d->m, d->m.tail); + if (err) { + return err; + } + } + } + } + + return 0; +} + + +/// Top level directory operations /// +int lfs2_mkdir(lfs2_t *lfs2, const char *path) { + LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path); + // deorphan if we haven't yet, needed at most once after poweron + int err = lfs2_fs_forceconsistency(lfs2); + if (err) { + LFS2_TRACE("lfs2_mkdir -> %d", err); + return err; + } + + lfs2_mdir_t cwd; + uint16_t id; + err = lfs2_dir_find(lfs2, &cwd, &path, &id); + if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) { + LFS2_TRACE("lfs2_mkdir -> %d", (err < 0) ? err : LFS2_ERR_EXIST); + return (err < 0) ? err : LFS2_ERR_EXIST; + } + + // check that name fits + lfs2_size_t nlen = strlen(path); + if (nlen > lfs2->name_max) { + LFS2_TRACE("lfs2_mkdir -> %d", LFS2_ERR_NAMETOOLONG); + return LFS2_ERR_NAMETOOLONG; + } + + // build up new directory + lfs2_alloc_ack(lfs2); + lfs2_mdir_t dir; + err = lfs2_dir_alloc(lfs2, &dir); + if (err) { + LFS2_TRACE("lfs2_mkdir -> %d", err); + return err; + } + + // find end of list + lfs2_mdir_t pred = cwd; + while (pred.split) { + err = lfs2_dir_fetch(lfs2, &pred, pred.tail); + if (err) { + LFS2_TRACE("lfs2_mkdir -> %d", err); + return err; + } + } + + // setup dir + lfs2_pair_tole32(pred.tail); + err = lfs2_dir_commit(lfs2, &dir, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), pred.tail})); + lfs2_pair_fromle32(pred.tail); + if (err) { + LFS2_TRACE("lfs2_mkdir -> %d", err); + return err; + } + + // current block end of list? + if (cwd.split) { + // update tails, this creates a desync + lfs2_fs_preporphans(lfs2, +1); + lfs2_pair_tole32(dir.pair); + err = lfs2_dir_commit(lfs2, &pred, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair})); + lfs2_pair_fromle32(dir.pair); + if (err) { + LFS2_TRACE("lfs2_mkdir -> %d", err); + return err; + } + lfs2_fs_preporphans(lfs2, -1); + } + + // now insert into our parent block + lfs2_pair_tole32(dir.pair); + err = lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_CREATE, id, 0), NULL}, + {LFS2_MKTAG(LFS2_TYPE_DIR, id, nlen), path}, + {LFS2_MKTAG(LFS2_TYPE_DIRSTRUCT, id, 8), dir.pair}, + {!cwd.split + ? LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8) + : LFS2_MKTAG(LFS2_FROM_NOOP, 0, 0), dir.pair})); + lfs2_pair_fromle32(dir.pair); + if (err) { + LFS2_TRACE("lfs2_mkdir -> %d", err); + return err; + } + + LFS2_TRACE("lfs2_mkdir -> %d", 0); + return 0; +} + +int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { + LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path); + lfs2_stag_t tag = lfs2_dir_find(lfs2, &dir->m, &path, NULL); + if (tag < 0) { + LFS2_TRACE("lfs2_dir_open -> %d", tag); + return tag; + } + + if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { + LFS2_TRACE("lfs2_dir_open -> %d", LFS2_ERR_NOTDIR); + return LFS2_ERR_NOTDIR; + } + + lfs2_block_t pair[2]; + if (lfs2_tag_id(tag) == 0x3ff) { + // handle root dir separately + pair[0] = lfs2->root[0]; + pair[1] = lfs2->root[1]; + } else { + // get dir pair from parent + lfs2_stag_t res = lfs2_dir_get(lfs2, &dir->m, LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair); + if (res < 0) { + LFS2_TRACE("lfs2_dir_open -> %d", res); + return res; + } + lfs2_pair_fromle32(pair); + } + + // fetch first pair + int err = lfs2_dir_fetch(lfs2, &dir->m, pair); + if (err) { + LFS2_TRACE("lfs2_dir_open -> %d", err); + return err; + } + + // setup entry + dir->head[0] = dir->m.pair[0]; + dir->head[1] = dir->m.pair[1]; + dir->id = 0; + dir->pos = 0; + + // add to list of mdirs + dir->type = LFS2_TYPE_DIR; + dir->next = (lfs2_dir_t*)lfs2->mlist; + lfs2->mlist = (struct lfs2_mlist*)dir; + + LFS2_TRACE("lfs2_dir_open -> %d", 0); + return 0; +} + +int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) { + LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir); + // remove from list of mdirs + for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) { + if (*p == (struct lfs2_mlist*)dir) { + *p = (*p)->next; + break; + } + } + + LFS2_TRACE("lfs2_dir_close -> %d", 0); + return 0; +} + +int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { + LFS2_TRACE("lfs2_dir_read(%p, %p, %p)", + (void*)lfs2, (void*)dir, (void*)info); + memset(info, 0, sizeof(*info)); + + // special offset for '.' and '..' + if (dir->pos == 0) { + info->type = LFS2_TYPE_DIR; + strcpy(info->name, "."); + dir->pos += 1; + LFS2_TRACE("lfs2_dir_read -> %d", true); + return true; + } else if (dir->pos == 1) { + info->type = LFS2_TYPE_DIR; + strcpy(info->name, ".."); + dir->pos += 1; + LFS2_TRACE("lfs2_dir_read -> %d", true); + return true; + } + + while (true) { + if (dir->id == dir->m.count) { + if (!dir->m.split) { + LFS2_TRACE("lfs2_dir_read -> %d", false); + return false; + } + + int err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail); + if (err) { + LFS2_TRACE("lfs2_dir_read -> %d", err); + return err; + } + + dir->id = 0; + } + + int err = lfs2_dir_getinfo(lfs2, &dir->m, dir->id, info); + if (err && err != LFS2_ERR_NOENT) { + LFS2_TRACE("lfs2_dir_read -> %d", err); + return err; + } + + dir->id += 1; + if (err != LFS2_ERR_NOENT) { + break; + } + } + + dir->pos += 1; + LFS2_TRACE("lfs2_dir_read -> %d", true); + return true; +} + +int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { + LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")", + (void*)lfs2, (void*)dir, off); + // simply walk from head dir + int err = lfs2_dir_rewind(lfs2, dir); + if (err) { + LFS2_TRACE("lfs2_dir_seek -> %d", err); + return err; + } + + // first two for ./.. + dir->pos = lfs2_min(2, off); + off -= dir->pos; + + while (off != 0) { + dir->id = lfs2_min(dir->m.count, off); + dir->pos += dir->id; + off -= dir->id; + + if (dir->id == dir->m.count) { + if (!dir->m.split) { + LFS2_TRACE("lfs2_dir_seek -> %d", LFS2_ERR_INVAL); + return LFS2_ERR_INVAL; + } + + err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail); + if (err) { + LFS2_TRACE("lfs2_dir_seek -> %d", err); + return err; + } + } + } + + LFS2_TRACE("lfs2_dir_seek -> %d", 0); + return 0; +} + +lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) { + LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir); + (void)lfs2; + LFS2_TRACE("lfs2_dir_tell -> %"PRId32, dir->pos); + return dir->pos; +} + +int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) { + LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir); + // reload the head dir + int err = lfs2_dir_fetch(lfs2, &dir->m, dir->head); + if (err) { + LFS2_TRACE("lfs2_dir_rewind -> %d", err); + return err; + } + + dir->m.pair[0] = dir->head[0]; + dir->m.pair[1] = dir->head[1]; + dir->id = 0; + dir->pos = 0; + LFS2_TRACE("lfs2_dir_rewind -> %d", 0); + return 0; +} + + +/// File index list operations /// +static int lfs2_ctz_index(lfs2_t *lfs2, lfs2_off_t *off) { + lfs2_off_t size = *off; + lfs2_off_t b = lfs2->cfg->block_size - 2*4; + lfs2_off_t i = size / b; + if (i == 0) { + return 0; + } + + i = (size - 4*(lfs2_popc(i-1)+2)) / b; + *off = size - b*i - 4*lfs2_popc(i); + return i; +} + +static int lfs2_ctz_find(lfs2_t *lfs2, + const lfs2_cache_t *pcache, lfs2_cache_t *rcache, + lfs2_block_t head, lfs2_size_t size, + lfs2_size_t pos, lfs2_block_t *block, lfs2_off_t *off) { + if (size == 0) { + *block = LFS2_BLOCK_NULL; + *off = 0; + return 0; + } + + lfs2_off_t current = lfs2_ctz_index(lfs2, &(lfs2_off_t){size-1}); + lfs2_off_t target = lfs2_ctz_index(lfs2, &pos); + + while (current > target) { + lfs2_size_t skip = lfs2_min( + lfs2_npw2(current-target+1) - 1, + lfs2_ctz(current)); + + int err = lfs2_bd_read(lfs2, + pcache, rcache, sizeof(head), + head, 4*skip, &head, sizeof(head)); + head = lfs2_fromle32(head); + if (err) { + return err; + } + + LFS2_ASSERT(head >= 2 && head <= lfs2->cfg->block_count); + current -= 1 << skip; + } + + *block = head; + *off = pos; + return 0; +} + +static int lfs2_ctz_extend(lfs2_t *lfs2, + lfs2_cache_t *pcache, lfs2_cache_t *rcache, + lfs2_block_t head, lfs2_size_t size, + lfs2_block_t *block, lfs2_off_t *off) { + while (true) { + // go ahead and grab a block + lfs2_block_t nblock; + int err = lfs2_alloc(lfs2, &nblock); + if (err) { + return err; + } + LFS2_ASSERT(nblock >= 2 && nblock <= lfs2->cfg->block_count); + + { + err = lfs2_bd_erase(lfs2, nblock); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (size == 0) { + *block = nblock; + *off = 0; + return 0; + } + + size -= 1; + lfs2_off_t index = lfs2_ctz_index(lfs2, &size); + size += 1; + + // just copy out the last block if it is incomplete + if (size != lfs2->cfg->block_size) { + for (lfs2_off_t i = 0; i < size; i++) { + uint8_t data; + err = lfs2_bd_read(lfs2, + NULL, rcache, size-i, + head, i, &data, 1); + if (err) { + return err; + } + + err = lfs2_bd_prog(lfs2, + pcache, rcache, true, + nblock, i, &data, 1); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + *block = nblock; + *off = size; + return 0; + } + + // append block + index += 1; + lfs2_size_t skips = lfs2_ctz(index) + 1; + + for (lfs2_off_t i = 0; i < skips; i++) { + head = lfs2_tole32(head); + err = lfs2_bd_prog(lfs2, pcache, rcache, true, + nblock, 4*i, &head, 4); + head = lfs2_fromle32(head); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (i != skips-1) { + err = lfs2_bd_read(lfs2, + NULL, rcache, sizeof(head), + head, 4*i, &head, sizeof(head)); + head = lfs2_fromle32(head); + if (err) { + return err; + } + } + + LFS2_ASSERT(head >= 2 && head <= lfs2->cfg->block_count); + } + + *block = nblock; + *off = 4*skips; + return 0; + } + +relocate: + LFS2_DEBUG("Bad block at %"PRIx32, nblock); + + // just clear cache and try a new block + lfs2_cache_drop(lfs2, pcache); + } +} + +static int lfs2_ctz_traverse(lfs2_t *lfs2, + const lfs2_cache_t *pcache, lfs2_cache_t *rcache, + lfs2_block_t head, lfs2_size_t size, + int (*cb)(void*, lfs2_block_t), void *data) { + if (size == 0) { + return 0; + } + + lfs2_off_t index = lfs2_ctz_index(lfs2, &(lfs2_off_t){size-1}); + + while (true) { + int err = cb(data, head); + if (err) { + return err; + } + + if (index == 0) { + return 0; + } + + lfs2_block_t heads[2]; + int count = 2 - (index & 1); + err = lfs2_bd_read(lfs2, + pcache, rcache, count*sizeof(head), + head, 0, &heads, count*sizeof(head)); + heads[0] = lfs2_fromle32(heads[0]); + heads[1] = lfs2_fromle32(heads[1]); + if (err) { + return err; + } + + for (int i = 0; i < count-1; i++) { + err = cb(data, heads[i]); + if (err) { + return err; + } + } + + head = heads[count-1]; + index -= count; + } +} + + +/// Top level file operations /// +int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file, + const char *path, int flags, + const struct lfs2_file_config *cfg) { + LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {" + ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})", + (void*)lfs2, (void*)file, path, flags, + (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); + + // deorphan if we haven't yet, needed at most once after poweron + if ((flags & 3) != LFS2_O_RDONLY) { + int err = lfs2_fs_forceconsistency(lfs2); + if (err) { + LFS2_TRACE("lfs2_file_opencfg -> %d", err); + return err; + } + } + + // setup simple file details + int err; + file->cfg = cfg; + file->flags = flags | LFS2_F_OPENED; + file->pos = 0; + file->off = 0; + file->cache.buffer = NULL; + + // allocate entry for file if it doesn't exist + lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id); + if (tag < 0 && !(tag == LFS2_ERR_NOENT && file->id != 0x3ff)) { + err = tag; + goto cleanup; + } + + // get id, add to list of mdirs to catch update changes + file->type = LFS2_TYPE_REG; + file->next = (lfs2_file_t*)lfs2->mlist; + lfs2->mlist = (struct lfs2_mlist*)file; + + if (tag == LFS2_ERR_NOENT) { + if (!(flags & LFS2_O_CREAT)) { + err = LFS2_ERR_NOENT; + goto cleanup; + } + + // check that name fits + lfs2_size_t nlen = strlen(path); + if (nlen > lfs2->name_max) { + err = LFS2_ERR_NAMETOOLONG; + goto cleanup; + } + + // get next slot and create entry to remember name + err = lfs2_dir_commit(lfs2, &file->m, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_CREATE, file->id, 0), NULL}, + {LFS2_MKTAG(LFS2_TYPE_REG, file->id, nlen), path}, + {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0), NULL})); + if (err) { + err = LFS2_ERR_NAMETOOLONG; + goto cleanup; + } + + tag = LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, 0); + } else if (flags & LFS2_O_EXCL) { + err = LFS2_ERR_EXIST; + goto cleanup; + } else if (lfs2_tag_type3(tag) != LFS2_TYPE_REG) { + err = LFS2_ERR_ISDIR; + goto cleanup; + } else if (flags & LFS2_O_TRUNC) { + // truncate if requested + tag = LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0); + file->flags |= LFS2_F_DIRTY; + } else { + // try to load what's on disk, if it's inlined we'll fix it later + tag = lfs2_dir_get(lfs2, &file->m, LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, file->id, 8), &file->ctz); + if (tag < 0) { + err = tag; + goto cleanup; + } + lfs2_ctz_fromle32(&file->ctz); + } + + // fetch attrs + for (unsigned i = 0; i < file->cfg->attr_count; i++) { + if ((file->flags & 3) != LFS2_O_WRONLY) { + lfs2_stag_t res = lfs2_dir_get(lfs2, &file->m, + LFS2_MKTAG(0x7ff, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_USERATTR + file->cfg->attrs[i].type, + file->id, file->cfg->attrs[i].size), + file->cfg->attrs[i].buffer); + if (res < 0 && res != LFS2_ERR_NOENT) { + err = res; + goto cleanup; + } + } + + if ((file->flags & 3) != LFS2_O_RDONLY) { + if (file->cfg->attrs[i].size > lfs2->attr_max) { + err = LFS2_ERR_NOSPC; + goto cleanup; + } + + file->flags |= LFS2_F_DIRTY; + } + } + + // allocate buffer if needed + if (file->cfg->buffer) { + file->cache.buffer = file->cfg->buffer; + } else { + file->cache.buffer = lfs2_malloc(lfs2->cfg->cache_size); + if (!file->cache.buffer) { + err = LFS2_ERR_NOMEM; + goto cleanup; + } + } + + // zero to avoid information leak + lfs2_cache_zero(lfs2, &file->cache); + + if (lfs2_tag_type3(tag) == LFS2_TYPE_INLINESTRUCT) { + // load inline files + file->ctz.head = LFS2_BLOCK_INLINE; + file->ctz.size = lfs2_tag_size(tag); + file->flags |= LFS2_F_INLINE; + file->cache.block = file->ctz.head; + file->cache.off = 0; + file->cache.size = lfs2->cfg->cache_size; + + // don't always read (may be new/trunc file) + if (file->ctz.size > 0) { + lfs2_stag_t res = lfs2_dir_get(lfs2, &file->m, + LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, file->id, + lfs2_min(file->cache.size, 0x3fe)), + file->cache.buffer); + if (res < 0) { + err = res; + goto cleanup; + } + } + } + + LFS2_TRACE("lfs2_file_opencfg -> %d", 0); + return 0; + +cleanup: + // clean up lingering resources + file->flags |= LFS2_F_ERRED; + lfs2_file_close(lfs2, file); + LFS2_TRACE("lfs2_file_opencfg -> %d", err); + return err; +} + +int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, + const char *path, int flags) { + LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)", + (void*)lfs2, (void*)file, path, flags); + static const struct lfs2_file_config defaults = {0}; + int err = lfs2_file_opencfg(lfs2, file, path, flags, &defaults); + LFS2_TRACE("lfs2_file_open -> %d", err); + return err; +} + +int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) { + LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + + int err = lfs2_file_sync(lfs2, file); + + // remove from list of mdirs + for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) { + if (*p == (struct lfs2_mlist*)file) { + *p = (*p)->next; + break; + } + } + + // clean up memory + if (!file->cfg->buffer) { + lfs2_free(file->cache.buffer); + } + + file->flags &= ~LFS2_F_OPENED; + LFS2_TRACE("lfs2_file_close -> %d", err); + return err; +} + +static int lfs2_file_relocate(lfs2_t *lfs2, lfs2_file_t *file) { + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + + while (true) { + // just relocate what exists into new block + lfs2_block_t nblock; + int err = lfs2_alloc(lfs2, &nblock); + if (err) { + return err; + } + + err = lfs2_bd_erase(lfs2, nblock); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // either read from dirty cache or disk + for (lfs2_off_t i = 0; i < file->off; i++) { + uint8_t data; + if (file->flags & LFS2_F_INLINE) { + err = lfs2_dir_getread(lfs2, &file->m, + // note we evict inline files before they can be dirty + NULL, &file->cache, file->off-i, + LFS2_MKTAG(0xfff, 0x1ff, 0), + LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0), + i, &data, 1); + if (err) { + return err; + } + } else { + err = lfs2_bd_read(lfs2, + &file->cache, &lfs2->rcache, file->off-i, + file->block, i, &data, 1); + if (err) { + return err; + } + } + + err = lfs2_bd_prog(lfs2, + &lfs2->pcache, &lfs2->rcache, true, + nblock, i, &data, 1); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + // copy over new state of file + memcpy(file->cache.buffer, lfs2->pcache.buffer, lfs2->cfg->cache_size); + file->cache.block = lfs2->pcache.block; + file->cache.off = lfs2->pcache.off; + file->cache.size = lfs2->pcache.size; + lfs2_cache_zero(lfs2, &lfs2->pcache); + + file->block = nblock; + file->flags |= LFS2_F_WRITING; + return 0; + +relocate: + LFS2_DEBUG("Bad block at %"PRIx32, nblock); + + // just clear cache and try a new block + lfs2_cache_drop(lfs2, &lfs2->pcache); + } +} + +static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) { + file->off = file->pos; + lfs2_alloc_ack(lfs2); + int err = lfs2_file_relocate(lfs2, file); + if (err) { + return err; + } + + file->flags &= ~LFS2_F_INLINE; + return 0; +} + +static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) { + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + + if (file->flags & LFS2_F_READING) { + if (!(file->flags & LFS2_F_INLINE)) { + lfs2_cache_drop(lfs2, &file->cache); + } + file->flags &= ~LFS2_F_READING; + } + + if (file->flags & LFS2_F_WRITING) { + lfs2_off_t pos = file->pos; + + if (!(file->flags & LFS2_F_INLINE)) { + // copy over anything after current branch + lfs2_file_t orig = { + .ctz.head = file->ctz.head, + .ctz.size = file->ctz.size, + .flags = LFS2_O_RDONLY | LFS2_F_OPENED, + .pos = file->pos, + .cache = lfs2->rcache, + }; + lfs2_cache_drop(lfs2, &lfs2->rcache); + + while (file->pos < file->ctz.size) { + // copy over a byte at a time, leave it up to caching + // to make this efficient + uint8_t data; + lfs2_ssize_t res = lfs2_file_read(lfs2, &orig, &data, 1); + if (res < 0) { + return res; + } + + res = lfs2_file_write(lfs2, file, &data, 1); + if (res < 0) { + return res; + } + + // keep our reference to the rcache in sync + if (lfs2->rcache.block != LFS2_BLOCK_NULL) { + lfs2_cache_drop(lfs2, &orig.cache); + lfs2_cache_drop(lfs2, &lfs2->rcache); + } + } + + // write out what we have + while (true) { + int err = lfs2_bd_flush(lfs2, &file->cache, &lfs2->rcache, true); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + break; + +relocate: + LFS2_DEBUG("Bad block at %"PRIx32, file->block); + err = lfs2_file_relocate(lfs2, file); + if (err) { + return err; + } + } + } else { + file->pos = lfs2_max(file->pos, file->ctz.size); + } + + // actual file updates + file->ctz.head = file->block; + file->ctz.size = file->pos; + file->flags &= ~LFS2_F_WRITING; + file->flags |= LFS2_F_DIRTY; + + file->pos = pos; + } + + return 0; +} + +int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) { + LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + + while (true) { + int err = lfs2_file_flush(lfs2, file); + if (err) { + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_sync -> %d", err); + return err; + } + + if ((file->flags & LFS2_F_DIRTY) && + !(file->flags & LFS2_F_ERRED) && + !lfs2_pair_isnull(file->m.pair)) { + // update dir entry + uint16_t type; + const void *buffer; + lfs2_size_t size; + struct lfs2_ctz ctz; + if (file->flags & LFS2_F_INLINE) { + // inline the whole file + type = LFS2_TYPE_INLINESTRUCT; + buffer = file->cache.buffer; + size = file->ctz.size; + } else { + // update the ctz reference + type = LFS2_TYPE_CTZSTRUCT; + // copy ctz so alloc will work during a relocate + ctz = file->ctz; + lfs2_ctz_tole32(&ctz); + buffer = &ctz; + size = sizeof(ctz); + } + + // commit file data and attributes + err = lfs2_dir_commit(lfs2, &file->m, LFS2_MKATTRS( + {LFS2_MKTAG(type, file->id, size), buffer}, + {LFS2_MKTAG(LFS2_FROM_USERATTRS, file->id, + file->cfg->attr_count), file->cfg->attrs})); + if (err) { + if (err == LFS2_ERR_NOSPC && (file->flags & LFS2_F_INLINE)) { + goto relocate; + } + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_sync -> %d", err); + return err; + } + + file->flags &= ~LFS2_F_DIRTY; + } + + LFS2_TRACE("lfs2_file_sync -> %d", 0); + return 0; + +relocate: + // inline file doesn't fit anymore + err = lfs2_file_outline(lfs2, file); + if (err) { + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_sync -> %d", err); + return err; + } + } +} + +lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file, + void *buffer, lfs2_size_t size) { + LFS2_TRACE("lfs2_file_read(%p, %p, %p, %"PRIu32")", + (void*)lfs2, (void*)file, buffer, size); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + LFS2_ASSERT((file->flags & 3) != LFS2_O_WRONLY); + + uint8_t *data = buffer; + lfs2_size_t nsize = size; + + if (file->flags & LFS2_F_WRITING) { + // flush out any writes + int err = lfs2_file_flush(lfs2, file); + if (err) { + LFS2_TRACE("lfs2_file_read -> %"PRId32, err); + return err; + } + } + + if (file->pos >= file->ctz.size) { + // eof if past end + LFS2_TRACE("lfs2_file_read -> %"PRId32, 0); + return 0; + } + + size = lfs2_min(size, file->ctz.size - file->pos); + nsize = size; + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS2_F_READING) || + file->off == lfs2->cfg->block_size) { + if (!(file->flags & LFS2_F_INLINE)) { + int err = lfs2_ctz_find(lfs2, NULL, &file->cache, + file->ctz.head, file->ctz.size, + file->pos, &file->block, &file->off); + if (err) { + LFS2_TRACE("lfs2_file_read -> %"PRId32, err); + return err; + } + } else { + file->block = LFS2_BLOCK_INLINE; + file->off = file->pos; + } + + file->flags |= LFS2_F_READING; + } + + // read as much as we can in current block + lfs2_size_t diff = lfs2_min(nsize, lfs2->cfg->block_size - file->off); + if (file->flags & LFS2_F_INLINE) { + int err = lfs2_dir_getread(lfs2, &file->m, + NULL, &file->cache, lfs2->cfg->block_size, + LFS2_MKTAG(0xfff, 0x1ff, 0), + LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0), + file->off, data, diff); + if (err) { + LFS2_TRACE("lfs2_file_read -> %"PRId32, err); + return err; + } + } else { + int err = lfs2_bd_read(lfs2, + NULL, &file->cache, lfs2->cfg->block_size, + file->block, file->off, data, diff); + if (err) { + LFS2_TRACE("lfs2_file_read -> %"PRId32, err); + return err; + } + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + } + + LFS2_TRACE("lfs2_file_read -> %"PRId32, size); + return size; +} + +lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file, + const void *buffer, lfs2_size_t size) { + LFS2_TRACE("lfs2_file_write(%p, %p, %p, %"PRIu32")", + (void*)lfs2, (void*)file, buffer, size); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY); + + const uint8_t *data = buffer; + lfs2_size_t nsize = size; + + if (file->flags & LFS2_F_READING) { + // drop any reads + int err = lfs2_file_flush(lfs2, file); + if (err) { + LFS2_TRACE("lfs2_file_write -> %"PRId32, err); + return err; + } + } + + if ((file->flags & LFS2_O_APPEND) && file->pos < file->ctz.size) { + file->pos = file->ctz.size; + } + + if (file->pos + size > lfs2->file_max) { + // Larger than file limit? + LFS2_TRACE("lfs2_file_write -> %"PRId32, LFS2_ERR_FBIG); + return LFS2_ERR_FBIG; + } + + if (!(file->flags & LFS2_F_WRITING) && file->pos > file->ctz.size) { + // fill with zeros + lfs2_off_t pos = file->pos; + file->pos = file->ctz.size; + + while (file->pos < pos) { + lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1); + if (res < 0) { + LFS2_TRACE("lfs2_file_write -> %"PRId32, res); + return res; + } + } + } + + if ((file->flags & LFS2_F_INLINE) && + lfs2_max(file->pos+nsize, file->ctz.size) > + lfs2_min(0x3fe, lfs2_min( + lfs2->cfg->cache_size, lfs2->cfg->block_size/8))) { + // inline file doesn't fit anymore + int err = lfs2_file_outline(lfs2, file); + if (err) { + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_write -> %"PRId32, err); + return err; + } + } + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS2_F_WRITING) || + file->off == lfs2->cfg->block_size) { + if (!(file->flags & LFS2_F_INLINE)) { + if (!(file->flags & LFS2_F_WRITING) && file->pos > 0) { + // find out which block we're extending from + int err = lfs2_ctz_find(lfs2, NULL, &file->cache, + file->ctz.head, file->ctz.size, + file->pos-1, &file->block, &file->off); + if (err) { + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_write -> %"PRId32, err); + return err; + } + + // mark cache as dirty since we may have read data into it + lfs2_cache_zero(lfs2, &file->cache); + } + + // extend file with new blocks + lfs2_alloc_ack(lfs2); + int err = lfs2_ctz_extend(lfs2, &file->cache, &lfs2->rcache, + file->block, file->pos, + &file->block, &file->off); + if (err) { + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_write -> %"PRId32, err); + return err; + } + } else { + file->block = LFS2_BLOCK_INLINE; + file->off = file->pos; + } + + file->flags |= LFS2_F_WRITING; + } + + // program as much as we can in current block + lfs2_size_t diff = lfs2_min(nsize, lfs2->cfg->block_size - file->off); + while (true) { + int err = lfs2_bd_prog(lfs2, &file->cache, &lfs2->rcache, true, + file->block, file->off, data, diff); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + goto relocate; + } + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_write -> %"PRId32, err); + return err; + } + + break; +relocate: + err = lfs2_file_relocate(lfs2, file); + if (err) { + file->flags |= LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_write -> %"PRId32, err); + return err; + } + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + + lfs2_alloc_ack(lfs2); + } + + file->flags &= ~LFS2_F_ERRED; + LFS2_TRACE("lfs2_file_write -> %"PRId32, size); + return size; +} + +lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file, + lfs2_soff_t off, int whence) { + LFS2_TRACE("lfs2_file_seek(%p, %p, %"PRId32", %d)", + (void*)lfs2, (void*)file, off, whence); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + + // write out everything beforehand, may be noop if rdonly + int err = lfs2_file_flush(lfs2, file); + if (err) { + LFS2_TRACE("lfs2_file_seek -> %"PRId32, err); + return err; + } + + // find new pos + lfs2_off_t npos = file->pos; + if (whence == LFS2_SEEK_SET) { + npos = off; + } else if (whence == LFS2_SEEK_CUR) { + npos = file->pos + off; + } else if (whence == LFS2_SEEK_END) { + npos = file->ctz.size + off; + } + + if (npos > lfs2->file_max) { + // file position out of range + LFS2_TRACE("lfs2_file_seek -> %"PRId32, LFS2_ERR_INVAL); + return LFS2_ERR_INVAL; + } + + // update pos + file->pos = npos; + LFS2_TRACE("lfs2_file_seek -> %"PRId32, npos); + return npos; +} + +int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { + LFS2_TRACE("lfs2_file_truncate(%p, %p, %"PRIu32")", + (void*)lfs2, (void*)file, size); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY); + + if (size > LFS2_FILE_MAX) { + LFS2_TRACE("lfs2_file_truncate -> %d", LFS2_ERR_INVAL); + return LFS2_ERR_INVAL; + } + + lfs2_off_t pos = file->pos; + lfs2_off_t oldsize = lfs2_file_size(lfs2, file); + if (size < oldsize) { + // need to flush since directly changing metadata + int err = lfs2_file_flush(lfs2, file); + if (err) { + LFS2_TRACE("lfs2_file_truncate -> %d", err); + return err; + } + + // lookup new head in ctz skip list + err = lfs2_ctz_find(lfs2, NULL, &file->cache, + file->ctz.head, file->ctz.size, + size, &file->block, &file->off); + if (err) { + LFS2_TRACE("lfs2_file_truncate -> %d", err); + return err; + } + + file->ctz.head = file->block; + file->ctz.size = size; + file->flags |= LFS2_F_DIRTY | LFS2_F_READING; + } else if (size > oldsize) { + // flush+seek if not already at end + if (file->pos != oldsize) { + lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_END); + if (res < 0) { + LFS2_TRACE("lfs2_file_truncate -> %d", res); + return (int)res; + } + } + + // fill with zeros + while (file->pos < size) { + lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1); + if (res < 0) { + LFS2_TRACE("lfs2_file_truncate -> %d", res); + return (int)res; + } + } + } + + // restore pos + lfs2_soff_t res = lfs2_file_seek(lfs2, file, pos, LFS2_SEEK_SET); + if (res < 0) { + LFS2_TRACE("lfs2_file_truncate -> %d", res); + return (int)res; + } + + LFS2_TRACE("lfs2_file_truncate -> %d", 0); + return 0; +} + +lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) { + LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + (void)lfs2; + LFS2_TRACE("lfs2_file_tell -> %"PRId32, file->pos); + return file->pos; +} + +int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) { + LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file); + lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_SET); + if (res < 0) { + LFS2_TRACE("lfs2_file_rewind -> %d", res); + return (int)res; + } + + LFS2_TRACE("lfs2_file_rewind -> %d", 0); + return 0; +} + +lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) { + LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file); + LFS2_ASSERT(file->flags & LFS2_F_OPENED); + (void)lfs2; + if (file->flags & LFS2_F_WRITING) { + LFS2_TRACE("lfs2_file_size -> %"PRId32, + lfs2_max(file->pos, file->ctz.size)); + return lfs2_max(file->pos, file->ctz.size); + } else { + LFS2_TRACE("lfs2_file_size -> %"PRId32, file->ctz.size); + return file->ctz.size; + } +} + + +/// General fs operations /// +int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { + LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info); + lfs2_mdir_t cwd; + lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); + if (tag < 0) { + LFS2_TRACE("lfs2_stat -> %d", tag); + return (int)tag; + } + + int err = lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info); + LFS2_TRACE("lfs2_stat -> %d", err); + return err; +} + +int lfs2_remove(lfs2_t *lfs2, const char *path) { + LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path); + // deorphan if we haven't yet, needed at most once after poweron + int err = lfs2_fs_forceconsistency(lfs2); + if (err) { + LFS2_TRACE("lfs2_remove -> %d", err); + return err; + } + + lfs2_mdir_t cwd; + lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); + if (tag < 0 || lfs2_tag_id(tag) == 0x3ff) { + LFS2_TRACE("lfs2_remove -> %d", (tag < 0) ? tag : LFS2_ERR_INVAL); + return (tag < 0) ? (int)tag : LFS2_ERR_INVAL; + } + + lfs2_mdir_t dir; + if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { + // must be empty before removal + lfs2_block_t pair[2]; + lfs2_stag_t res = lfs2_dir_get(lfs2, &cwd, LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair); + if (res < 0) { + LFS2_TRACE("lfs2_remove -> %d", res); + return (int)res; + } + lfs2_pair_fromle32(pair); + + err = lfs2_dir_fetch(lfs2, &dir, pair); + if (err) { + LFS2_TRACE("lfs2_remove -> %d", err); + return err; + } + + if (dir.count > 0 || dir.split) { + LFS2_TRACE("lfs2_remove -> %d", LFS2_ERR_NOTEMPTY); + return LFS2_ERR_NOTEMPTY; + } + + // mark fs as orphaned + lfs2_fs_preporphans(lfs2, +1); + } + + // delete the entry + err = lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(tag), 0), NULL})); + if (err) { + LFS2_TRACE("lfs2_remove -> %d", err); + return err; + } + + if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { + // fix orphan + lfs2_fs_preporphans(lfs2, -1); + + err = lfs2_fs_pred(lfs2, dir.pair, &cwd); + if (err) { + LFS2_TRACE("lfs2_remove -> %d", err); + return err; + } + + err = lfs2_dir_drop(lfs2, &cwd, &dir); + if (err) { + LFS2_TRACE("lfs2_remove -> %d", err); + return err; + } + } + + LFS2_TRACE("lfs2_remove -> %d", 0); + return 0; +} + +int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) { + LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath); + + // deorphan if we haven't yet, needed at most once after poweron + int err = lfs2_fs_forceconsistency(lfs2); + if (err) { + LFS2_TRACE("lfs2_rename -> %d", err); + return err; + } + + // find old entry + lfs2_mdir_t oldcwd; + lfs2_stag_t oldtag = lfs2_dir_find(lfs2, &oldcwd, &oldpath, NULL); + if (oldtag < 0 || lfs2_tag_id(oldtag) == 0x3ff) { + LFS2_TRACE("lfs2_rename -> %d", (oldtag < 0) ? oldtag : LFS2_ERR_INVAL); + return (oldtag < 0) ? (int)oldtag : LFS2_ERR_INVAL; + } + + // find new entry + lfs2_mdir_t newcwd; + uint16_t newid; + lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid); + if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) && + !(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) { + LFS2_TRACE("lfs2_rename -> %d", (prevtag < 0) ? prevtag : LFS2_ERR_INVAL); + return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL; + } + + lfs2_mdir_t prevdir; + if (prevtag == LFS2_ERR_NOENT) { + // check that name fits + lfs2_size_t nlen = strlen(newpath); + if (nlen > lfs2->name_max) { + LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NAMETOOLONG); + return LFS2_ERR_NAMETOOLONG; + } + } else if (lfs2_tag_type3(prevtag) != lfs2_tag_type3(oldtag)) { + LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_ISDIR); + return LFS2_ERR_ISDIR; + } else if (lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) { + // must be empty before removal + lfs2_block_t prevpair[2]; + lfs2_stag_t res = lfs2_dir_get(lfs2, &newcwd, LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, newid, 8), prevpair); + if (res < 0) { + LFS2_TRACE("lfs2_rename -> %d", res); + return (int)res; + } + lfs2_pair_fromle32(prevpair); + + // must be empty before removal + err = lfs2_dir_fetch(lfs2, &prevdir, prevpair); + if (err) { + LFS2_TRACE("lfs2_rename -> %d", err); + return err; + } + + if (prevdir.count > 0 || prevdir.split) { + LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NOTEMPTY); + return LFS2_ERR_NOTEMPTY; + } + + // mark fs as orphaned + lfs2_fs_preporphans(lfs2, +1); + } + + // create move to fix later + uint16_t newoldtagid = lfs2_tag_id(oldtag); + if (lfs2_pair_cmp(oldcwd.pair, newcwd.pair) == 0 && + prevtag == LFS2_ERR_NOENT && newid <= newoldtagid) { + // there is a small chance we are being renamed in the same directory + // to an id less than our old id, the global update to handle this + // is a bit messy + newoldtagid += 1; + } + + lfs2_fs_prepmove(lfs2, newoldtagid, oldcwd.pair); + + // move over all attributes + err = lfs2_dir_commit(lfs2, &newcwd, LFS2_MKATTRS( + {prevtag != LFS2_ERR_NOENT + ? LFS2_MKTAG(LFS2_TYPE_DELETE, newid, 0) + : LFS2_MKTAG(LFS2_FROM_NOOP, 0, 0), NULL}, + {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL}, + {LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), + newpath}, + {LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd})); + if (err) { + LFS2_TRACE("lfs2_rename -> %d", err); + return err; + } + + // let commit clean up after move (if we're different! otherwise move + // logic already fixed it for us) + if (lfs2_pair_cmp(oldcwd.pair, newcwd.pair) != 0) { + err = lfs2_dir_commit(lfs2, &oldcwd, NULL, 0); + if (err) { + LFS2_TRACE("lfs2_rename -> %d", err); + return err; + } + } + + if (prevtag != LFS2_ERR_NOENT && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) { + // fix orphan + lfs2_fs_preporphans(lfs2, -1); + + err = lfs2_fs_pred(lfs2, prevdir.pair, &newcwd); + if (err) { + LFS2_TRACE("lfs2_rename -> %d", err); + return err; + } + + err = lfs2_dir_drop(lfs2, &newcwd, &prevdir); + if (err) { + LFS2_TRACE("lfs2_rename -> %d", err); + return err; + } + } + + LFS2_TRACE("lfs2_rename -> %d", 0); + return 0; +} + +lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path, + uint8_t type, void *buffer, lfs2_size_t size) { + LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", + (void*)lfs2, path, type, buffer, size); + lfs2_mdir_t cwd; + lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); + if (tag < 0) { + LFS2_TRACE("lfs2_getattr -> %"PRId32, tag); + return tag; + } + + uint16_t id = lfs2_tag_id(tag); + if (id == 0x3ff) { + // special case for root + id = 0; + int err = lfs2_dir_fetch(lfs2, &cwd, lfs2->root); + if (err) { + LFS2_TRACE("lfs2_getattr -> %"PRId32, err); + return err; + } + } + + tag = lfs2_dir_get(lfs2, &cwd, LFS2_MKTAG(0x7ff, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_USERATTR + type, + id, lfs2_min(size, lfs2->attr_max)), + buffer); + if (tag < 0) { + if (tag == LFS2_ERR_NOENT) { + LFS2_TRACE("lfs2_getattr -> %"PRId32, LFS2_ERR_NOATTR); + return LFS2_ERR_NOATTR; + } + + LFS2_TRACE("lfs2_getattr -> %"PRId32, tag); + return tag; + } + + size = lfs2_tag_size(tag); + LFS2_TRACE("lfs2_getattr -> %"PRId32, size); + return size; +} + +static int lfs2_commitattr(lfs2_t *lfs2, const char *path, + uint8_t type, const void *buffer, lfs2_size_t size) { + lfs2_mdir_t cwd; + lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); + if (tag < 0) { + return tag; + } + + uint16_t id = lfs2_tag_id(tag); + if (id == 0x3ff) { + // special case for root + id = 0; + int err = lfs2_dir_fetch(lfs2, &cwd, lfs2->root); + if (err) { + return err; + } + } + + return lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_USERATTR + type, id, size), buffer})); +} + +int lfs2_setattr(lfs2_t *lfs2, const char *path, + uint8_t type, const void *buffer, lfs2_size_t size) { + LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", + (void*)lfs2, path, type, buffer, size); + if (size > lfs2->attr_max) { + LFS2_TRACE("lfs2_setattr -> %d", LFS2_ERR_NOSPC); + return LFS2_ERR_NOSPC; + } + + int err = lfs2_commitattr(lfs2, path, type, buffer, size); + LFS2_TRACE("lfs2_setattr -> %d", err); + return err; +} + +int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) { + LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type); + int err = lfs2_commitattr(lfs2, path, type, NULL, 0x3ff); + LFS2_TRACE("lfs2_removeattr -> %d", err); + return err; +} + + +/// Filesystem operations /// +static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { + lfs2->cfg = cfg; + int err = 0; + + // validate that the lfs2-cfg sizes were initiated properly before + // performing any arithmetic logics with them + LFS2_ASSERT(lfs2->cfg->read_size != 0); + LFS2_ASSERT(lfs2->cfg->prog_size != 0); + LFS2_ASSERT(lfs2->cfg->cache_size != 0); + + // check that block size is a multiple of cache size is a multiple + // of prog and read sizes + LFS2_ASSERT(lfs2->cfg->cache_size % lfs2->cfg->read_size == 0); + LFS2_ASSERT(lfs2->cfg->cache_size % lfs2->cfg->prog_size == 0); + LFS2_ASSERT(lfs2->cfg->block_size % lfs2->cfg->cache_size == 0); + + // check that the block size is large enough to fit ctz pointers + LFS2_ASSERT(4*lfs2_npw2(LFS2_BLOCK_NULL / (lfs2->cfg->block_size-2*4)) + <= lfs2->cfg->block_size); + + // block_cycles = 0 is no longer supported. + // + // block_cycles is the number of erase cycles before littlefs evicts + // metadata logs as a part of wear leveling. Suggested values are in the + // range of 100-1000, or set block_cycles to -1 to disable block-level + // wear-leveling. + LFS2_ASSERT(lfs2->cfg->block_cycles != 0); + + + // setup read cache + if (lfs2->cfg->read_buffer) { + lfs2->rcache.buffer = lfs2->cfg->read_buffer; + } else { + lfs2->rcache.buffer = lfs2_malloc(lfs2->cfg->cache_size); + if (!lfs2->rcache.buffer) { + err = LFS2_ERR_NOMEM; + goto cleanup; + } + } + + // setup program cache + if (lfs2->cfg->prog_buffer) { + lfs2->pcache.buffer = lfs2->cfg->prog_buffer; + } else { + lfs2->pcache.buffer = lfs2_malloc(lfs2->cfg->cache_size); + if (!lfs2->pcache.buffer) { + err = LFS2_ERR_NOMEM; + goto cleanup; + } + } + + // zero to avoid information leaks + lfs2_cache_zero(lfs2, &lfs2->rcache); + lfs2_cache_zero(lfs2, &lfs2->pcache); + + // setup lookahead, must be multiple of 64-bits, 32-bit aligned + LFS2_ASSERT(lfs2->cfg->lookahead_size > 0); + LFS2_ASSERT(lfs2->cfg->lookahead_size % 8 == 0 && + (uintptr_t)lfs2->cfg->lookahead_buffer % 4 == 0); + if (lfs2->cfg->lookahead_buffer) { + lfs2->free.buffer = lfs2->cfg->lookahead_buffer; + } else { + lfs2->free.buffer = lfs2_malloc(lfs2->cfg->lookahead_size); + if (!lfs2->free.buffer) { + err = LFS2_ERR_NOMEM; + goto cleanup; + } + } + + // check that the size limits are sane + LFS2_ASSERT(lfs2->cfg->name_max <= LFS2_NAME_MAX); + lfs2->name_max = lfs2->cfg->name_max; + if (!lfs2->name_max) { + lfs2->name_max = LFS2_NAME_MAX; + } + + LFS2_ASSERT(lfs2->cfg->file_max <= LFS2_FILE_MAX); + lfs2->file_max = lfs2->cfg->file_max; + if (!lfs2->file_max) { + lfs2->file_max = LFS2_FILE_MAX; + } + + LFS2_ASSERT(lfs2->cfg->attr_max <= LFS2_ATTR_MAX); + lfs2->attr_max = lfs2->cfg->attr_max; + if (!lfs2->attr_max) { + lfs2->attr_max = LFS2_ATTR_MAX; + } + + // setup default state + lfs2->root[0] = LFS2_BLOCK_NULL; + lfs2->root[1] = LFS2_BLOCK_NULL; + lfs2->mlist = NULL; + lfs2->seed = 0; + lfs2->gstate = (struct lfs2_gstate){0}; + lfs2->gpending = (struct lfs2_gstate){0}; + lfs2->gdelta = (struct lfs2_gstate){0}; +#ifdef LFS2_MIGRATE + lfs2->lfs21 = NULL; +#endif + + return 0; + +cleanup: + lfs2_deinit(lfs2); + return err; +} + +static int lfs2_deinit(lfs2_t *lfs2) { + // free allocated memory + if (!lfs2->cfg->read_buffer) { + lfs2_free(lfs2->rcache.buffer); + } + + if (!lfs2->cfg->prog_buffer) { + lfs2_free(lfs2->pcache.buffer); + } + + if (!lfs2->cfg->lookahead_buffer) { + lfs2_free(lfs2->free.buffer); + } + + return 0; +} + +int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) { + LFS2_TRACE("lfs2_format(%p, %p {.context=%p, " + ".read=%p, .prog=%p, .erase=%p, .sync=%p, " + ".read_size=%"PRIu32", .prog_size=%"PRIu32", " + ".block_size=%"PRIu32", .block_count=%"PRIu32", " + ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".lookahead_size=%"PRIu32", .read_buffer=%p, " + ".prog_buffer=%p, .lookahead_buffer=%p, " + ".name_max=%"PRIu32", .file_max=%"PRIu32", " + ".attr_max=%"PRIu32"})", + (void*)lfs2, (void*)cfg, cfg->context, + (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, + (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, + cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, + cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, + cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, + cfg->name_max, cfg->file_max, cfg->attr_max); + int err = 0; + { + err = lfs2_init(lfs2, cfg); + if (err) { + LFS2_TRACE("lfs2_format -> %d", err); + return err; + } + + // create free lookahead + memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); + lfs2->free.off = 0; + lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, + lfs2->cfg->block_count); + lfs2->free.i = 0; + lfs2_alloc_ack(lfs2); + + // create root dir + lfs2_mdir_t root; + err = lfs2_dir_alloc(lfs2, &root); + if (err) { + goto cleanup; + } + + // write one superblock + lfs2_superblock_t superblock = { + .version = LFS2_DISK_VERSION, + .block_size = lfs2->cfg->block_size, + .block_count = lfs2->cfg->block_count, + .name_max = lfs2->name_max, + .file_max = lfs2->file_max, + .attr_max = lfs2->attr_max, + }; + + lfs2_superblock_tole32(&superblock); + err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0), NULL}, + {LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), "littlefs"}, + {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), + &superblock})); + if (err) { + goto cleanup; + } + + // sanity check that fetch works + err = lfs2_dir_fetch(lfs2, &root, (const lfs2_block_t[2]){0, 1}); + if (err) { + goto cleanup; + } + + // force compaction to prevent accidentally mounting any + // older version of littlefs that may live on disk + root.erased = false; + err = lfs2_dir_commit(lfs2, &root, NULL, 0); + if (err) { + goto cleanup; + } + } + +cleanup: + lfs2_deinit(lfs2); + LFS2_TRACE("lfs2_format -> %d", err); + return err; +} + +int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) { + LFS2_TRACE("lfs2_mount(%p, %p {.context=%p, " + ".read=%p, .prog=%p, .erase=%p, .sync=%p, " + ".read_size=%"PRIu32", .prog_size=%"PRIu32", " + ".block_size=%"PRIu32", .block_count=%"PRIu32", " + ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".lookahead_size=%"PRIu32", .read_buffer=%p, " + ".prog_buffer=%p, .lookahead_buffer=%p, " + ".name_max=%"PRIu32", .file_max=%"PRIu32", " + ".attr_max=%"PRIu32"})", + (void*)lfs2, (void*)cfg, cfg->context, + (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, + (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, + cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, + cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, + cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, + cfg->name_max, cfg->file_max, cfg->attr_max); + int err = lfs2_init(lfs2, cfg); + if (err) { + LFS2_TRACE("lfs2_mount -> %d", err); + return err; + } + + // scan directory blocks for superblock and any global updates + lfs2_mdir_t dir = {.tail = {0, 1}}; + while (!lfs2_pair_isnull(dir.tail)) { + // fetch next block in tail list + lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail, + LFS2_MKTAG(0x7ff, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), + NULL, + lfs2_dir_find_match, &(struct lfs2_dir_find_match){ + lfs2, "littlefs", 8}); + if (tag < 0) { + err = tag; + goto cleanup; + } + + // has superblock? + if (tag && !lfs2_tag_isdelete(tag)) { + // update root + lfs2->root[0] = dir.pair[0]; + lfs2->root[1] = dir.pair[1]; + + // grab superblock + lfs2_superblock_t superblock; + tag = lfs2_dir_get(lfs2, &dir, LFS2_MKTAG(0x7ff, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), + &superblock); + if (tag < 0) { + err = tag; + goto cleanup; + } + lfs2_superblock_fromle32(&superblock); + + // check version + uint16_t major_version = (0xffff & (superblock.version >> 16)); + uint16_t minor_version = (0xffff & (superblock.version >> 0)); + if ((major_version != LFS2_DISK_VERSION_MAJOR || + minor_version > LFS2_DISK_VERSION_MINOR)) { + LFS2_ERROR("Invalid version %"PRIu16".%"PRIu16, + major_version, minor_version); + err = LFS2_ERR_INVAL; + goto cleanup; + } + + // check superblock configuration + if (superblock.name_max) { + if (superblock.name_max > lfs2->name_max) { + LFS2_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")", + superblock.name_max, lfs2->name_max); + err = LFS2_ERR_INVAL; + goto cleanup; + } + + lfs2->name_max = superblock.name_max; + } + + if (superblock.file_max) { + if (superblock.file_max > lfs2->file_max) { + LFS2_ERROR("Unsupported file_max (%"PRIu32" > %"PRIu32")", + superblock.file_max, lfs2->file_max); + err = LFS2_ERR_INVAL; + goto cleanup; + } + + lfs2->file_max = superblock.file_max; + } + + if (superblock.attr_max) { + if (superblock.attr_max > lfs2->attr_max) { + LFS2_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")", + superblock.attr_max, lfs2->attr_max); + err = LFS2_ERR_INVAL; + goto cleanup; + } + + lfs2->attr_max = superblock.attr_max; + } + } + + // has gstate? + err = lfs2_dir_getgstate(lfs2, &dir, &lfs2->gpending); + if (err) { + goto cleanup; + } + } + + // found superblock? + if (lfs2_pair_isnull(lfs2->root)) { + err = LFS2_ERR_INVAL; + goto cleanup; + } + + // update littlefs with gstate + lfs2->gpending.tag += !lfs2_tag_isvalid(lfs2->gpending.tag); + lfs2->gstate = lfs2->gpending; + if (lfs2_gstate_hasmove(&lfs2->gstate)) { + LFS2_DEBUG("Found move %"PRIx32" %"PRIx32" %"PRIx16, + lfs2->gstate.pair[0], + lfs2->gstate.pair[1], + lfs2_tag_id(lfs2->gstate.tag)); + } + + // setup free lookahead + lfs2->free.off = lfs2->seed % lfs2->cfg->block_size; + lfs2->free.size = 0; + lfs2->free.i = 0; + lfs2_alloc_ack(lfs2); + + LFS2_TRACE("lfs2_mount -> %d", 0); + return 0; + +cleanup: + lfs2_unmount(lfs2); + LFS2_TRACE("lfs2_mount -> %d", err); + return err; +} + +int lfs2_unmount(lfs2_t *lfs2) { + LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2); + int err = lfs2_deinit(lfs2); + LFS2_TRACE("lfs2_unmount -> %d", err); + return err; +} + + +/// Filesystem filesystem operations /// +int lfs2_fs_traverse(lfs2_t *lfs2, + int (*cb)(void *data, lfs2_block_t block), void *data) { + LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)", + (void*)lfs2, (void*)(uintptr_t)cb, data); + // iterate over metadata pairs + lfs2_mdir_t dir = {.tail = {0, 1}}; + +#ifdef LFS2_MIGRATE + // also consider v1 blocks during migration + if (lfs2->lfs21) { + int err = lfs21_traverse(lfs2, cb, data); + if (err) { + LFS2_TRACE("lfs2_fs_traverse -> %d", err); + return err; + } + + dir.tail[0] = lfs2->root[0]; + dir.tail[1] = lfs2->root[1]; + } +#endif + + while (!lfs2_pair_isnull(dir.tail)) { + for (int i = 0; i < 2; i++) { + int err = cb(data, dir.tail[i]); + if (err) { + LFS2_TRACE("lfs2_fs_traverse -> %d", err); + return err; + } + } + + // iterate through ids in directory + int err = lfs2_dir_fetch(lfs2, &dir, dir.tail); + if (err) { + LFS2_TRACE("lfs2_fs_traverse -> %d", err); + return err; + } + + for (uint16_t id = 0; id < dir.count; id++) { + struct lfs2_ctz ctz; + lfs2_stag_t tag = lfs2_dir_get(lfs2, &dir, LFS2_MKTAG(0x700, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_STRUCT, id, sizeof(ctz)), &ctz); + if (tag < 0) { + if (tag == LFS2_ERR_NOENT) { + continue; + } + LFS2_TRACE("lfs2_fs_traverse -> %d", tag); + return tag; + } + lfs2_ctz_fromle32(&ctz); + + if (lfs2_tag_type3(tag) == LFS2_TYPE_CTZSTRUCT) { + err = lfs2_ctz_traverse(lfs2, NULL, &lfs2->rcache, + ctz.head, ctz.size, cb, data); + if (err) { + LFS2_TRACE("lfs2_fs_traverse -> %d", err); + return err; + } + } + } + } + + // iterate over any open files + for (lfs2_file_t *f = (lfs2_file_t*)lfs2->mlist; f; f = f->next) { + if (f->type != LFS2_TYPE_REG) { + continue; + } + + if ((f->flags & LFS2_F_DIRTY) && !(f->flags & LFS2_F_INLINE)) { + int err = lfs2_ctz_traverse(lfs2, &f->cache, &lfs2->rcache, + f->ctz.head, f->ctz.size, cb, data); + if (err) { + LFS2_TRACE("lfs2_fs_traverse -> %d", err); + return err; + } + } + + if ((f->flags & LFS2_F_WRITING) && !(f->flags & LFS2_F_INLINE)) { + int err = lfs2_ctz_traverse(lfs2, &f->cache, &lfs2->rcache, + f->block, f->pos, cb, data); + if (err) { + LFS2_TRACE("lfs2_fs_traverse -> %d", err); + return err; + } + } + } + + LFS2_TRACE("lfs2_fs_traverse -> %d", 0); + return 0; +} + +static int lfs2_fs_pred(lfs2_t *lfs2, + const lfs2_block_t pair[2], lfs2_mdir_t *pdir) { + // iterate over all directory directory entries + pdir->tail[0] = 0; + pdir->tail[1] = 1; + while (!lfs2_pair_isnull(pdir->tail)) { + if (lfs2_pair_cmp(pdir->tail, pair) == 0) { + return 0; + } + + int err = lfs2_dir_fetch(lfs2, pdir, pdir->tail); + if (err) { + return err; + } + } + + return LFS2_ERR_NOENT; +} + +struct lfs2_fs_parent_match { + lfs2_t *lfs2; + const lfs2_block_t pair[2]; +}; + +static int lfs2_fs_parent_match(void *data, + lfs2_tag_t tag, const void *buffer) { + struct lfs2_fs_parent_match *find = data; + lfs2_t *lfs2 = find->lfs2; + const struct lfs2_diskoff *disk = buffer; + (void)tag; + + lfs2_block_t child[2]; + int err = lfs2_bd_read(lfs2, + &lfs2->pcache, &lfs2->rcache, lfs2->cfg->block_size, + disk->block, disk->off, &child, sizeof(child)); + if (err) { + return err; + } + + lfs2_pair_fromle32(child); + return (lfs2_pair_cmp(child, find->pair) == 0) ? LFS2_CMP_EQ : LFS2_CMP_LT; +} + +static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2], + lfs2_mdir_t *parent) { + // use fetchmatch with callback to find pairs + parent->tail[0] = 0; + parent->tail[1] = 1; + while (!lfs2_pair_isnull(parent->tail)) { + lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail, + LFS2_MKTAG(0x7ff, 0, 0x3ff), + LFS2_MKTAG(LFS2_TYPE_DIRSTRUCT, 0, 8), + NULL, + lfs2_fs_parent_match, &(struct lfs2_fs_parent_match){ + lfs2, {pair[0], pair[1]}}); + if (tag && tag != LFS2_ERR_NOENT) { + return tag; + } + } + + return LFS2_ERR_NOENT; +} + +static int lfs2_fs_relocate(lfs2_t *lfs2, + const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]) { + // update internal root + if (lfs2_pair_cmp(oldpair, lfs2->root) == 0) { + LFS2_DEBUG("Relocating root %"PRIx32" %"PRIx32, + newpair[0], newpair[1]); + lfs2->root[0] = newpair[0]; + lfs2->root[1] = newpair[1]; + } + + // update internally tracked dirs + for (struct lfs2_mlist *d = lfs2->mlist; d; d = d->next) { + if (lfs2_pair_cmp(oldpair, d->m.pair) == 0) { + d->m.pair[0] = newpair[0]; + d->m.pair[1] = newpair[1]; + } + } + + // find parent + lfs2_mdir_t parent; + lfs2_stag_t tag = lfs2_fs_parent(lfs2, oldpair, &parent); + if (tag < 0 && tag != LFS2_ERR_NOENT) { + return tag; + } + + if (tag != LFS2_ERR_NOENT) { + // update disk, this creates a desync + lfs2_fs_preporphans(lfs2, +1); + + lfs2_pair_tole32(newpair); + int err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS({tag, newpair})); + lfs2_pair_fromle32(newpair); + if (err) { + return err; + } + + // next step, clean up orphans + lfs2_fs_preporphans(lfs2, -1); + } + + // find pred + int err = lfs2_fs_pred(lfs2, oldpair, &parent); + if (err && err != LFS2_ERR_NOENT) { + return err; + } + + // if we can't find dir, it must be new + if (err != LFS2_ERR_NOENT) { + // replace bad pair, either we clean up desync, or no desync occured + lfs2_pair_tole32(newpair); + err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_TAIL + parent.split, 0x3ff, 8), newpair})); + lfs2_pair_fromle32(newpair); + if (err) { + return err; + } + } + + return 0; +} + +static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans) { + lfs2->gpending.tag += orphans; + lfs2_gstate_xororphans(&lfs2->gdelta, &lfs2->gpending, + lfs2_gstate_hasorphans(&lfs2->gpending)); + lfs2_gstate_xororphans(&lfs2->gpending, &lfs2->gpending, + lfs2_gstate_hasorphans(&lfs2->gpending)); +} + +static void lfs2_fs_prepmove(lfs2_t *lfs2, + uint16_t id, const lfs2_block_t pair[2]) { + lfs2_gstate_xormove(&lfs2->gdelta, &lfs2->gpending, id, pair); + lfs2_gstate_xormove(&lfs2->gpending, &lfs2->gpending, id, pair); +} + + +static int lfs2_fs_demove(lfs2_t *lfs2) { + if (!lfs2_gstate_hasmove(&lfs2->gstate)) { + return 0; + } + + // Fix bad moves + LFS2_DEBUG("Fixing move %"PRIx32" %"PRIx32" %"PRIx16, + lfs2->gstate.pair[0], + lfs2->gstate.pair[1], + lfs2_tag_id(lfs2->gstate.tag)); + + // fetch and delete the moved entry + lfs2_mdir_t movedir; + int err = lfs2_dir_fetch(lfs2, &movedir, lfs2->gstate.pair); + if (err) { + return err; + } + + // rely on cancel logic inside commit + err = lfs2_dir_commit(lfs2, &movedir, NULL, 0); + if (err) { + return err; + } + + return 0; +} + +static int lfs2_fs_deorphan(lfs2_t *lfs2) { + if (!lfs2_gstate_hasorphans(&lfs2->gstate)) { + return 0; + } + + // Fix any orphans + lfs2_mdir_t pdir = {.split = true}; + lfs2_mdir_t dir = {.tail = {0, 1}}; + + // iterate over all directory directory entries + while (!lfs2_pair_isnull(dir.tail)) { + int err = lfs2_dir_fetch(lfs2, &dir, dir.tail); + if (err) { + return err; + } + + // check head blocks for orphans + if (!pdir.split) { + // check if we have a parent + lfs2_mdir_t parent; + lfs2_stag_t tag = lfs2_fs_parent(lfs2, pdir.tail, &parent); + if (tag < 0 && tag != LFS2_ERR_NOENT) { + return tag; + } + + if (tag == LFS2_ERR_NOENT) { + // we are an orphan + LFS2_DEBUG("Fixing orphan %"PRIx32" %"PRIx32, + pdir.tail[0], pdir.tail[1]); + + err = lfs2_dir_drop(lfs2, &pdir, &dir); + if (err) { + return err; + } + + break; + } + + lfs2_block_t pair[2]; + lfs2_stag_t res = lfs2_dir_get(lfs2, &parent, + LFS2_MKTAG(0x7ff, 0x3ff, 0), tag, pair); + if (res < 0) { + return res; + } + lfs2_pair_fromle32(pair); + + if (!lfs2_pair_sync(pair, pdir.tail)) { + // we have desynced + LFS2_DEBUG("Fixing half-orphan %"PRIx32" %"PRIx32, + pair[0], pair[1]); + + lfs2_pair_tole32(pair); + err = lfs2_dir_commit(lfs2, &pdir, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), pair})); + lfs2_pair_fromle32(pair); + if (err) { + return err; + } + + break; + } + } + + memcpy(&pdir, &dir, sizeof(pdir)); + } + + // mark orphans as fixed + lfs2_fs_preporphans(lfs2, -lfs2_gstate_getorphans(&lfs2->gstate)); + lfs2->gstate = lfs2->gpending; + return 0; +} + +static int lfs2_fs_forceconsistency(lfs2_t *lfs2) { + int err = lfs2_fs_demove(lfs2); + if (err) { + return err; + } + + err = lfs2_fs_deorphan(lfs2); + if (err) { + return err; + } + + return 0; +} + +static int lfs2_fs_size_count(void *p, lfs2_block_t block) { + (void)block; + lfs2_size_t *size = p; + *size += 1; + return 0; +} + +lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) { + LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2); + lfs2_size_t size = 0; + int err = lfs2_fs_traverse(lfs2, lfs2_fs_size_count, &size); + if (err) { + LFS2_TRACE("lfs2_fs_size -> %"PRId32, err); + return err; + } + + LFS2_TRACE("lfs2_fs_size -> %"PRId32, err); + return size; +} + +#ifdef LFS2_MIGRATE +////// Migration from littelfs v1 below this ////// + +/// Version info /// + +// Software library version +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS21_VERSION 0x00010007 +#define LFS21_VERSION_MAJOR (0xffff & (LFS21_VERSION >> 16)) +#define LFS21_VERSION_MINOR (0xffff & (LFS21_VERSION >> 0)) + +// Version of On-disk data structures +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS21_DISK_VERSION 0x00010001 +#define LFS21_DISK_VERSION_MAJOR (0xffff & (LFS21_DISK_VERSION >> 16)) +#define LFS21_DISK_VERSION_MINOR (0xffff & (LFS21_DISK_VERSION >> 0)) + + +/// v1 Definitions /// + +// File types +enum lfs21_type { + LFS21_TYPE_REG = 0x11, + LFS21_TYPE_DIR = 0x22, + LFS21_TYPE_SUPERBLOCK = 0x2e, +}; + +typedef struct lfs21 { + lfs2_block_t root[2]; +} lfs21_t; + +typedef struct lfs21_entry { + lfs2_off_t off; + + struct lfs21_disk_entry { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + union { + struct { + lfs2_block_t head; + lfs2_size_t size; + } file; + lfs2_block_t dir[2]; + } u; + } d; +} lfs21_entry_t; + +typedef struct lfs21_dir { + struct lfs21_dir *next; + lfs2_block_t pair[2]; + lfs2_off_t off; + + lfs2_block_t head[2]; + lfs2_off_t pos; + + struct lfs21_disk_dir { + uint32_t rev; + lfs2_size_t size; + lfs2_block_t tail[2]; + } d; +} lfs21_dir_t; + +typedef struct lfs21_superblock { + lfs2_off_t off; + + struct lfs21_disk_superblock { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + lfs2_block_t root[2]; + uint32_t block_size; + uint32_t block_count; + uint32_t version; + char magic[8]; + } d; +} lfs21_superblock_t; + + +/// Low-level wrappers v1->v2 /// +static void lfs21_crc(uint32_t *crc, const void *buffer, size_t size) { + *crc = lfs2_crc(*crc, buffer, size); +} + +static int lfs21_bd_read(lfs2_t *lfs2, lfs2_block_t block, + lfs2_off_t off, void *buffer, lfs2_size_t size) { + // if we ever do more than writes to alternating pairs, + // this may need to consider pcache + return lfs2_bd_read(lfs2, &lfs2->pcache, &lfs2->rcache, size, + block, off, buffer, size); +} + +static int lfs21_bd_crc(lfs2_t *lfs2, lfs2_block_t block, + lfs2_off_t off, lfs2_size_t size, uint32_t *crc) { + for (lfs2_off_t i = 0; i < size; i++) { + uint8_t c; + int err = lfs21_bd_read(lfs2, block, off+i, &c, 1); + if (err) { + return err; + } + + lfs21_crc(crc, &c, 1); + } + + return 0; +} + + +/// Endian swapping functions /// +static void lfs21_dir_fromle32(struct lfs21_disk_dir *d) { + d->rev = lfs2_fromle32(d->rev); + d->size = lfs2_fromle32(d->size); + d->tail[0] = lfs2_fromle32(d->tail[0]); + d->tail[1] = lfs2_fromle32(d->tail[1]); +} + +static void lfs21_dir_tole32(struct lfs21_disk_dir *d) { + d->rev = lfs2_tole32(d->rev); + d->size = lfs2_tole32(d->size); + d->tail[0] = lfs2_tole32(d->tail[0]); + d->tail[1] = lfs2_tole32(d->tail[1]); +} + +static void lfs21_entry_fromle32(struct lfs21_disk_entry *d) { + d->u.dir[0] = lfs2_fromle32(d->u.dir[0]); + d->u.dir[1] = lfs2_fromle32(d->u.dir[1]); +} + +static void lfs21_entry_tole32(struct lfs21_disk_entry *d) { + d->u.dir[0] = lfs2_tole32(d->u.dir[0]); + d->u.dir[1] = lfs2_tole32(d->u.dir[1]); +} + +static void lfs21_superblock_fromle32(struct lfs21_disk_superblock *d) { + d->root[0] = lfs2_fromle32(d->root[0]); + d->root[1] = lfs2_fromle32(d->root[1]); + d->block_size = lfs2_fromle32(d->block_size); + d->block_count = lfs2_fromle32(d->block_count); + d->version = lfs2_fromle32(d->version); +} + + +///// Metadata pair and directory operations /// +static inline lfs2_size_t lfs21_entry_size(const lfs21_entry_t *entry) { + return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; +} + +static int lfs21_dir_fetch(lfs2_t *lfs2, + lfs21_dir_t *dir, const lfs2_block_t pair[2]) { + // copy out pair, otherwise may be aliasing dir + const lfs2_block_t tpair[2] = {pair[0], pair[1]}; + bool valid = false; + + // check both blocks for the most recent revision + for (int i = 0; i < 2; i++) { + struct lfs21_disk_dir test; + int err = lfs21_bd_read(lfs2, tpair[i], 0, &test, sizeof(test)); + lfs21_dir_fromle32(&test); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + continue; + } + return err; + } + + if (valid && lfs2_scmp(test.rev, dir->d.rev) < 0) { + continue; + } + + if ((0x7fffffff & test.size) < sizeof(test)+4 || + (0x7fffffff & test.size) > lfs2->cfg->block_size) { + continue; + } + + uint32_t crc = LFS2_BLOCK_NULL; + lfs21_dir_tole32(&test); + lfs21_crc(&crc, &test, sizeof(test)); + lfs21_dir_fromle32(&test); + err = lfs21_bd_crc(lfs2, tpair[i], sizeof(test), + (0x7fffffff & test.size) - sizeof(test), &crc); + if (err) { + if (err == LFS2_ERR_CORRUPT) { + continue; + } + return err; + } + + if (crc != 0) { + continue; + } + + valid = true; + + // setup dir in case it's valid + dir->pair[0] = tpair[(i+0) % 2]; + dir->pair[1] = tpair[(i+1) % 2]; + dir->off = sizeof(dir->d); + dir->d = test; + } + + if (!valid) { + LFS2_ERROR("Corrupted dir pair at %" PRIx32 " %" PRIx32 , + tpair[0], tpair[1]); + return LFS2_ERR_CORRUPT; + } + + return 0; +} + +static int lfs21_dir_next(lfs2_t *lfs2, lfs21_dir_t *dir, lfs21_entry_t *entry) { + while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) { + if (!(0x80000000 & dir->d.size)) { + entry->off = dir->off; + return LFS2_ERR_NOENT; + } + + int err = lfs21_dir_fetch(lfs2, dir, dir->d.tail); + if (err) { + return err; + } + + dir->off = sizeof(dir->d); + dir->pos += sizeof(dir->d) + 4; + } + + int err = lfs21_bd_read(lfs2, dir->pair[0], dir->off, + &entry->d, sizeof(entry->d)); + lfs21_entry_fromle32(&entry->d); + if (err) { + return err; + } + + entry->off = dir->off; + dir->off += lfs21_entry_size(entry); + dir->pos += lfs21_entry_size(entry); + return 0; +} + +/// littlefs v1 specific operations /// +int lfs21_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data) { + if (lfs2_pair_isnull(lfs2->lfs21->root)) { + return 0; + } + + // iterate over metadata pairs + lfs21_dir_t dir; + lfs21_entry_t entry; + lfs2_block_t cwd[2] = {0, 1}; + + while (true) { + for (int i = 0; i < 2; i++) { + int err = cb(data, cwd[i]); + if (err) { + return err; + } + } + + int err = lfs21_dir_fetch(lfs2, &dir, cwd); + if (err) { + return err; + } + + // iterate over contents + while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { + err = lfs21_bd_read(lfs2, dir.pair[0], dir.off, + &entry.d, sizeof(entry.d)); + lfs21_entry_fromle32(&entry.d); + if (err) { + return err; + } + + dir.off += lfs21_entry_size(&entry); + if ((0x70 & entry.d.type) == (0x70 & LFS21_TYPE_REG)) { + err = lfs2_ctz_traverse(lfs2, NULL, &lfs2->rcache, + entry.d.u.file.head, entry.d.u.file.size, cb, data); + if (err) { + return err; + } + } + } + + // we also need to check if we contain a threaded v2 directory + lfs2_mdir_t dir2 = {.split=true, .tail={cwd[0], cwd[1]}}; + while (dir2.split) { + err = lfs2_dir_fetch(lfs2, &dir2, dir2.tail); + if (err) { + break; + } + + for (int i = 0; i < 2; i++) { + err = cb(data, dir2.pair[i]); + if (err) { + return err; + } + } + } + + cwd[0] = dir.d.tail[0]; + cwd[1] = dir.d.tail[1]; + + if (lfs2_pair_isnull(cwd)) { + break; + } + } + + return 0; +} + +static int lfs21_moved(lfs2_t *lfs2, const void *e) { + if (lfs2_pair_isnull(lfs2->lfs21->root)) { + return 0; + } + + // skip superblock + lfs21_dir_t cwd; + int err = lfs21_dir_fetch(lfs2, &cwd, (const lfs2_block_t[2]){0, 1}); + if (err) { + return err; + } + + // iterate over all directory directory entries + lfs21_entry_t entry; + while (!lfs2_pair_isnull(cwd.d.tail)) { + err = lfs21_dir_fetch(lfs2, &cwd, cwd.d.tail); + if (err) { + return err; + } + + while (true) { + err = lfs21_dir_next(lfs2, &cwd, &entry); + if (err && err != LFS2_ERR_NOENT) { + return err; + } + + if (err == LFS2_ERR_NOENT) { + break; + } + + if (!(0x80 & entry.d.type) && + memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) { + return true; + } + } + } + + return false; +} + +/// Filesystem operations /// +static int lfs21_mount(lfs2_t *lfs2, struct lfs21 *lfs21, + const struct lfs2_config *cfg) { + int err = 0; + { + err = lfs2_init(lfs2, cfg); + if (err) { + return err; + } + + lfs2->lfs21 = lfs21; + lfs2->lfs21->root[0] = LFS2_BLOCK_NULL; + lfs2->lfs21->root[1] = LFS2_BLOCK_NULL; + + // setup free lookahead + lfs2->free.off = 0; + lfs2->free.size = 0; + lfs2->free.i = 0; + lfs2_alloc_ack(lfs2); + + // load superblock + lfs21_dir_t dir; + lfs21_superblock_t superblock; + err = lfs21_dir_fetch(lfs2, &dir, (const lfs2_block_t[2]){0, 1}); + if (err && err != LFS2_ERR_CORRUPT) { + goto cleanup; + } + + if (!err) { + err = lfs21_bd_read(lfs2, dir.pair[0], sizeof(dir.d), + &superblock.d, sizeof(superblock.d)); + lfs21_superblock_fromle32(&superblock.d); + if (err) { + goto cleanup; + } + + lfs2->lfs21->root[0] = superblock.d.root[0]; + lfs2->lfs21->root[1] = superblock.d.root[1]; + } + + if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) { + LFS2_ERROR("Invalid superblock at %d %d", 0, 1); + err = LFS2_ERR_CORRUPT; + goto cleanup; + } + + uint16_t major_version = (0xffff & (superblock.d.version >> 16)); + uint16_t minor_version = (0xffff & (superblock.d.version >> 0)); + if ((major_version != LFS21_DISK_VERSION_MAJOR || + minor_version > LFS21_DISK_VERSION_MINOR)) { + LFS2_ERROR("Invalid version %d.%d", major_version, minor_version); + err = LFS2_ERR_INVAL; + goto cleanup; + } + + return 0; + } + +cleanup: + lfs2_deinit(lfs2); + return err; +} + +static int lfs21_unmount(lfs2_t *lfs2) { + return lfs2_deinit(lfs2); +} + +/// v1 migration /// +int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { + LFS2_TRACE("lfs2_migrate(%p, %p {.context=%p, " + ".read=%p, .prog=%p, .erase=%p, .sync=%p, " + ".read_size=%"PRIu32", .prog_size=%"PRIu32", " + ".block_size=%"PRIu32", .block_count=%"PRIu32", " + ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".lookahead_size=%"PRIu32", .read_buffer=%p, " + ".prog_buffer=%p, .lookahead_buffer=%p, " + ".name_max=%"PRIu32", .file_max=%"PRIu32", " + ".attr_max=%"PRIu32"})", + (void*)lfs2, (void*)cfg, cfg->context, + (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog, + (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync, + cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count, + cfg->block_cycles, cfg->cache_size, cfg->lookahead_size, + cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, + cfg->name_max, cfg->file_max, cfg->attr_max); + struct lfs21 lfs21; + int err = lfs21_mount(lfs2, &lfs21, cfg); + if (err) { + LFS2_TRACE("lfs2_migrate -> %d", err); + return err; + } + + { + // iterate through each directory, copying over entries + // into new directory + lfs21_dir_t dir1; + lfs2_mdir_t dir2; + dir1.d.tail[0] = lfs2->lfs21->root[0]; + dir1.d.tail[1] = lfs2->lfs21->root[1]; + while (!lfs2_pair_isnull(dir1.d.tail)) { + // iterate old dir + err = lfs21_dir_fetch(lfs2, &dir1, dir1.d.tail); + if (err) { + goto cleanup; + } + + // create new dir and bind as temporary pretend root + err = lfs2_dir_alloc(lfs2, &dir2); + if (err) { + goto cleanup; + } + + dir2.rev = dir1.d.rev; + dir1.head[0] = dir1.pair[0]; + dir1.head[1] = dir1.pair[1]; + lfs2->root[0] = dir2.pair[0]; + lfs2->root[1] = dir2.pair[1]; + + err = lfs2_dir_commit(lfs2, &dir2, NULL, 0); + if (err) { + goto cleanup; + } + + while (true) { + lfs21_entry_t entry1; + err = lfs21_dir_next(lfs2, &dir1, &entry1); + if (err && err != LFS2_ERR_NOENT) { + goto cleanup; + } + + if (err == LFS2_ERR_NOENT) { + break; + } + + // check that entry has not been moved + if (entry1.d.type & 0x80) { + int moved = lfs21_moved(lfs2, &entry1.d.u); + if (moved < 0) { + err = moved; + goto cleanup; + } + + if (moved) { + continue; + } + + entry1.d.type &= ~0x80; + } + + // also fetch name + char name[LFS2_NAME_MAX+1]; + memset(name, 0, sizeof(name)); + err = lfs21_bd_read(lfs2, dir1.pair[0], + entry1.off + 4+entry1.d.elen+entry1.d.alen, + name, entry1.d.nlen); + if (err) { + goto cleanup; + } + + bool isdir = (entry1.d.type == LFS21_TYPE_DIR); + + // create entry in new dir + err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root); + if (err) { + goto cleanup; + } + + uint16_t id; + err = lfs2_dir_find(lfs2, &dir2, &(const char*){name}, &id); + if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) { + err = (err < 0) ? err : LFS2_ERR_EXIST; + goto cleanup; + } + + lfs21_entry_tole32(&entry1.d); + err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_CREATE, id, 0), NULL}, + {LFS2_MKTAG( + isdir ? LFS2_TYPE_DIR : LFS2_TYPE_REG, + id, entry1.d.nlen), name}, + {LFS2_MKTAG( + isdir ? LFS2_TYPE_DIRSTRUCT : LFS2_TYPE_CTZSTRUCT, + id, sizeof(&entry1.d.u)), &entry1.d.u})); + lfs21_entry_fromle32(&entry1.d); + if (err) { + goto cleanup; + } + } + + if (!lfs2_pair_isnull(dir1.d.tail)) { + // find last block and update tail to thread into fs + err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root); + if (err) { + goto cleanup; + } + + while (dir2.split) { + err = lfs2_dir_fetch(lfs2, &dir2, dir2.tail); + if (err) { + goto cleanup; + } + } + + lfs2_pair_tole32(dir2.pair); + err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 0), + dir1.d.tail})); + lfs2_pair_fromle32(dir2.pair); + if (err) { + goto cleanup; + } + } + + // Copy over first block to thread into fs. Unfortunately + // if this fails there is not much we can do. + LFS2_DEBUG("Migrating %"PRIx32" %"PRIx32" -> %"PRIx32" %"PRIx32, + lfs2->root[0], lfs2->root[1], dir1.head[0], dir1.head[1]); + + err = lfs2_bd_erase(lfs2, dir1.head[1]); + if (err) { + goto cleanup; + } + + err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root); + if (err) { + goto cleanup; + } + + for (lfs2_off_t i = 0; i < dir2.off; i++) { + uint8_t dat; + err = lfs2_bd_read(lfs2, + NULL, &lfs2->rcache, dir2.off, + dir2.pair[0], i, &dat, 1); + if (err) { + goto cleanup; + } + + err = lfs2_bd_prog(lfs2, + &lfs2->pcache, &lfs2->rcache, true, + dir1.head[1], i, &dat, 1); + if (err) { + goto cleanup; + } + } + + err = lfs2_bd_flush(lfs2, &lfs2->pcache, &lfs2->rcache, true); + if (err) { + goto cleanup; + } + } + + // Create new superblock. This marks a successful migration! + err = lfs21_dir_fetch(lfs2, &dir1, (const lfs2_block_t[2]){0, 1}); + if (err) { + goto cleanup; + } + + dir2.pair[0] = dir1.pair[0]; + dir2.pair[1] = dir1.pair[1]; + dir2.rev = dir1.d.rev; + dir2.off = sizeof(dir2.rev); + dir2.etag = LFS2_BLOCK_NULL; + dir2.count = 0; + dir2.tail[0] = lfs2->lfs21->root[0]; + dir2.tail[1] = lfs2->lfs21->root[1]; + dir2.erased = false; + dir2.split = true; + + lfs2_superblock_t superblock = { + .version = LFS2_DISK_VERSION, + .block_size = lfs2->cfg->block_size, + .block_count = lfs2->cfg->block_count, + .name_max = lfs2->name_max, + .file_max = lfs2->file_max, + .attr_max = lfs2->attr_max, + }; + + lfs2_superblock_tole32(&superblock); + err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS( + {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0), NULL}, + {LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), "littlefs"}, + {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), + &superblock})); + if (err) { + goto cleanup; + } + + // sanity check that fetch works + err = lfs2_dir_fetch(lfs2, &dir2, (const lfs2_block_t[2]){0, 1}); + if (err) { + goto cleanup; + } + + // force compaction to prevent accidentally mounting v1 + dir2.erased = false; + err = lfs2_dir_commit(lfs2, &dir2, NULL, 0); + if (err) { + goto cleanup; + } + } + +cleanup: + lfs21_unmount(lfs2); + LFS2_TRACE("lfs2_migrate -> %d", err); + return err; +} + +#endif diff --git a/lib/littlefs/lfs2.h b/lib/littlefs/lfs2.h new file mode 100644 index 0000000000000..fdbe007cc9e21 --- /dev/null +++ b/lib/littlefs/lfs2.h @@ -0,0 +1,651 @@ +/* + * The little filesystem + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LFS2_H +#define LFS2_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/// Version info /// + +// Software library version +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS2_VERSION 0x00020001 +#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16)) +#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0)) + +// Version of On-disk data structures +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS2_DISK_VERSION 0x00020000 +#define LFS2_DISK_VERSION_MAJOR (0xffff & (LFS2_DISK_VERSION >> 16)) +#define LFS2_DISK_VERSION_MINOR (0xffff & (LFS2_DISK_VERSION >> 0)) + + +/// Definitions /// + +// Type definitions +typedef uint32_t lfs2_size_t; +typedef uint32_t lfs2_off_t; + +typedef int32_t lfs2_ssize_t; +typedef int32_t lfs2_soff_t; + +typedef uint32_t lfs2_block_t; + +// Maximum name size in bytes, may be redefined to reduce the size of the +// info struct. Limited to <= 1022. Stored in superblock and must be +// respected by other littlefs drivers. +#ifndef LFS2_NAME_MAX +#define LFS2_NAME_MAX 255 +#endif + +// Maximum size of a file in bytes, may be redefined to limit to support other +// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the +// functions lfs2_file_seek, lfs2_file_size, and lfs2_file_tell will return +// incorrect values due to using signed integers. Stored in superblock and +// must be respected by other littlefs drivers. +#ifndef LFS2_FILE_MAX +#define LFS2_FILE_MAX 2147483647 +#endif + +// Maximum size of custom attributes in bytes, may be redefined, but there is +// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022. +#ifndef LFS2_ATTR_MAX +#define LFS2_ATTR_MAX 1022 +#endif + +// Possible error codes, these are negative to allow +// valid positive return values +enum lfs2_error { + LFS2_ERR_OK = 0, // No error + LFS2_ERR_IO = -5, // Error during device operation + LFS2_ERR_CORRUPT = -84, // Corrupted + LFS2_ERR_NOENT = -2, // No directory entry + LFS2_ERR_EXIST = -17, // Entry already exists + LFS2_ERR_NOTDIR = -20, // Entry is not a dir + LFS2_ERR_ISDIR = -21, // Entry is a dir + LFS2_ERR_NOTEMPTY = -39, // Dir is not empty + LFS2_ERR_BADF = -9, // Bad file number + LFS2_ERR_FBIG = -27, // File too large + LFS2_ERR_INVAL = -22, // Invalid parameter + LFS2_ERR_NOSPC = -28, // No space left on device + LFS2_ERR_NOMEM = -12, // No more memory available + LFS2_ERR_NOATTR = -61, // No data/attr available + LFS2_ERR_NAMETOOLONG = -36, // File name too long +}; + +// File types +enum lfs2_type { + // file types + LFS2_TYPE_REG = 0x001, + LFS2_TYPE_DIR = 0x002, + + // internally used types + LFS2_TYPE_SPLICE = 0x400, + LFS2_TYPE_NAME = 0x000, + LFS2_TYPE_STRUCT = 0x200, + LFS2_TYPE_USERATTR = 0x300, + LFS2_TYPE_FROM = 0x100, + LFS2_TYPE_TAIL = 0x600, + LFS2_TYPE_GLOBALS = 0x700, + LFS2_TYPE_CRC = 0x500, + + // internally used type specializations + LFS2_TYPE_CREATE = 0x401, + LFS2_TYPE_DELETE = 0x4ff, + LFS2_TYPE_SUPERBLOCK = 0x0ff, + LFS2_TYPE_DIRSTRUCT = 0x200, + LFS2_TYPE_CTZSTRUCT = 0x202, + LFS2_TYPE_INLINESTRUCT = 0x201, + LFS2_TYPE_SOFTTAIL = 0x600, + LFS2_TYPE_HARDTAIL = 0x601, + LFS2_TYPE_MOVESTATE = 0x7ff, + + // internal chip sources + LFS2_FROM_NOOP = 0x000, + LFS2_FROM_MOVE = 0x101, + LFS2_FROM_USERATTRS = 0x102, +}; + +// File open flags +enum lfs2_open_flags { + // open flags + LFS2_O_RDONLY = 1, // Open a file as read only + LFS2_O_WRONLY = 2, // Open a file as write only + LFS2_O_RDWR = 3, // Open a file as read and write + LFS2_O_CREAT = 0x0100, // Create a file if it does not exist + LFS2_O_EXCL = 0x0200, // Fail if a file already exists + LFS2_O_TRUNC = 0x0400, // Truncate the existing file to zero size + LFS2_O_APPEND = 0x0800, // Move to end of file on every write + + // internally used flags + LFS2_F_DIRTY = 0x010000, // File does not match storage + LFS2_F_WRITING = 0x020000, // File has been written since last flush + LFS2_F_READING = 0x040000, // File has been read since last flush + LFS2_F_ERRED = 0x080000, // An error occured during write + LFS2_F_INLINE = 0x100000, // Currently inlined in directory entry + LFS2_F_OPENED = 0x200000, // File has been opened +}; + +// File seek flags +enum lfs2_whence_flags { + LFS2_SEEK_SET = 0, // Seek relative to an absolute position + LFS2_SEEK_CUR = 1, // Seek relative to the current file position + LFS2_SEEK_END = 2, // Seek relative to the end of the file +}; + + +// Configuration provided during initialization of the littlefs +struct lfs2_config { + // Opaque user provided context that can be used to pass + // information to the block device operations + void *context; + + // Read a region in a block. Negative error codes are propogated + // to the user. + int (*read)(const struct lfs2_config *c, lfs2_block_t block, + lfs2_off_t off, void *buffer, lfs2_size_t size); + + // Program a region in a block. The block must have previously + // been erased. Negative error codes are propogated to the user. + // May return LFS2_ERR_CORRUPT if the block should be considered bad. + int (*prog)(const struct lfs2_config *c, lfs2_block_t block, + lfs2_off_t off, const void *buffer, lfs2_size_t size); + + // Erase a block. A block must be erased before being programmed. + // The state of an erased block is undefined. Negative error codes + // are propogated to the user. + // May return LFS2_ERR_CORRUPT if the block should be considered bad. + int (*erase)(const struct lfs2_config *c, lfs2_block_t block); + + // Sync the state of the underlying block device. Negative error codes + // are propogated to the user. + int (*sync)(const struct lfs2_config *c); + + // Minimum size of a block read. All read operations will be a + // multiple of this value. + lfs2_size_t read_size; + + // Minimum size of a block program. All program operations will be a + // multiple of this value. + lfs2_size_t prog_size; + + // Size of an erasable block. This does not impact ram consumption and + // may be larger than the physical erase size. However, non-inlined files + // take up at minimum one block. Must be a multiple of the read + // and program sizes. + lfs2_size_t block_size; + + // Number of erasable blocks on the device. + lfs2_size_t block_count; + + // Number of erase cycles before littlefs evicts metadata logs and moves + // the metadata to another block. Suggested values are in the + // range 100-1000, with large values having better performance at the cost + // of less consistent wear distribution. + // + // Set to -1 to disable block-level wear-leveling. + int32_t block_cycles; + + // Size of block caches. Each cache buffers a portion of a block in RAM. + // The littlefs needs a read cache, a program cache, and one additional + // cache per file. Larger caches can improve performance by storing more + // data and reducing the number of disk accesses. Must be a multiple of + // the read and program sizes, and a factor of the block size. + lfs2_size_t cache_size; + + // Size of the lookahead buffer in bytes. A larger lookahead buffer + // increases the number of blocks found during an allocation pass. The + // lookahead buffer is stored as a compact bitmap, so each byte of RAM + // can track 8 blocks. Must be a multiple of 8. + lfs2_size_t lookahead_size; + + // Optional statically allocated read buffer. Must be cache_size. + // By default lfs2_malloc is used to allocate this buffer. + void *read_buffer; + + // Optional statically allocated program buffer. Must be cache_size. + // By default lfs2_malloc is used to allocate this buffer. + void *prog_buffer; + + // Optional statically allocated lookahead buffer. Must be lookahead_size + // and aligned to a 32-bit boundary. By default lfs2_malloc is used to + // allocate this buffer. + void *lookahead_buffer; + + // Optional upper limit on length of file names in bytes. No downside for + // larger names except the size of the info struct which is controlled by + // the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX when zero. Stored in + // superblock and must be respected by other littlefs drivers. + lfs2_size_t name_max; + + // Optional upper limit on files in bytes. No downside for larger files + // but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX when zero. Stored + // in superblock and must be respected by other littlefs drivers. + lfs2_size_t file_max; + + // Optional upper limit on custom attributes in bytes. No downside for + // larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to + // LFS2_ATTR_MAX when zero. + lfs2_size_t attr_max; +}; + +// File info structure +struct lfs2_info { + // Type of the file, either LFS2_TYPE_REG or LFS2_TYPE_DIR + uint8_t type; + + // Size of the file, only valid for REG files. Limited to 32-bits. + lfs2_size_t size; + + // Name of the file stored as a null-terminated string. Limited to + // LFS2_NAME_MAX+1, which can be changed by redefining LFS2_NAME_MAX to + // reduce RAM. LFS2_NAME_MAX is stored in superblock and must be + // respected by other littlefs drivers. + char name[LFS2_NAME_MAX+1]; +}; + +// Custom attribute structure, used to describe custom attributes +// committed atomically during file writes. +struct lfs2_attr { + // 8-bit type of attribute, provided by user and used to + // identify the attribute + uint8_t type; + + // Pointer to buffer containing the attribute + void *buffer; + + // Size of attribute in bytes, limited to LFS2_ATTR_MAX + lfs2_size_t size; +}; + +// Optional configuration provided during lfs2_file_opencfg +struct lfs2_file_config { + // Optional statically allocated file buffer. Must be cache_size. + // By default lfs2_malloc is used to allocate this buffer. + void *buffer; + + // Optional list of custom attributes related to the file. If the file + // is opened with read access, these attributes will be read from disk + // during the open call. If the file is opened with write access, the + // attributes will be written to disk every file sync or close. This + // write occurs atomically with update to the file's contents. + // + // Custom attributes are uniquely identified by an 8-bit type and limited + // to LFS2_ATTR_MAX bytes. When read, if the stored attribute is smaller + // than the buffer, it will be padded with zeros. If the stored attribute + // is larger, then it will be silently truncated. If the attribute is not + // found, it will be created implicitly. + struct lfs2_attr *attrs; + + // Number of custom attributes in the list + lfs2_size_t attr_count; +}; + + +/// internal littlefs data structures /// +typedef struct lfs2_cache { + lfs2_block_t block; + lfs2_off_t off; + lfs2_size_t size; + uint8_t *buffer; +} lfs2_cache_t; + +typedef struct lfs2_mdir { + lfs2_block_t pair[2]; + uint32_t rev; + lfs2_off_t off; + uint32_t etag; + uint16_t count; + bool erased; + bool split; + lfs2_block_t tail[2]; +} lfs2_mdir_t; + +// littlefs directory type +typedef struct lfs2_dir { + struct lfs2_dir *next; + uint16_t id; + uint8_t type; + lfs2_mdir_t m; + + lfs2_off_t pos; + lfs2_block_t head[2]; +} lfs2_dir_t; + +// littlefs file type +typedef struct lfs2_file { + struct lfs2_file *next; + uint16_t id; + uint8_t type; + lfs2_mdir_t m; + + struct lfs2_ctz { + lfs2_block_t head; + lfs2_size_t size; + } ctz; + + uint32_t flags; + lfs2_off_t pos; + lfs2_block_t block; + lfs2_off_t off; + lfs2_cache_t cache; + + const struct lfs2_file_config *cfg; +} lfs2_file_t; + +typedef struct lfs2_superblock { + uint32_t version; + lfs2_size_t block_size; + lfs2_size_t block_count; + lfs2_size_t name_max; + lfs2_size_t file_max; + lfs2_size_t attr_max; +} lfs2_superblock_t; + +// The littlefs filesystem type +typedef struct lfs2 { + lfs2_cache_t rcache; + lfs2_cache_t pcache; + + lfs2_block_t root[2]; + struct lfs2_mlist { + struct lfs2_mlist *next; + uint16_t id; + uint8_t type; + lfs2_mdir_t m; + } *mlist; + uint32_t seed; + + struct lfs2_gstate { + uint32_t tag; + lfs2_block_t pair[2]; + } gstate, gpending, gdelta; + + struct lfs2_free { + lfs2_block_t off; + lfs2_block_t size; + lfs2_block_t i; + lfs2_block_t ack; + uint32_t *buffer; + } free; + + const struct lfs2_config *cfg; + lfs2_size_t name_max; + lfs2_size_t file_max; + lfs2_size_t attr_max; + +#ifdef LFS2_MIGRATE + struct lfs21 *lfs21; +#endif +} lfs2_t; + + +/// Filesystem functions /// + +// Format a block device with the littlefs +// +// Requires a littlefs object and config struct. This clobbers the littlefs +// object, and does not leave the filesystem mounted. The config struct must +// be zeroed for defaults and backwards compatibility. +// +// Returns a negative error code on failure. +int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *config); + +// Mounts a littlefs +// +// Requires a littlefs object and config struct. Multiple filesystems +// may be mounted simultaneously with multiple littlefs objects. Both +// lfs2 and config must be allocated while mounted. The config struct must +// be zeroed for defaults and backwards compatibility. +// +// Returns a negative error code on failure. +int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *config); + +// Unmounts a littlefs +// +// Does nothing besides releasing any allocated resources. +// Returns a negative error code on failure. +int lfs2_unmount(lfs2_t *lfs2); + +/// General operations /// + +// Removes a file or directory +// +// If removing a directory, the directory must be empty. +// Returns a negative error code on failure. +int lfs2_remove(lfs2_t *lfs2, const char *path); + +// Rename or move a file or directory +// +// If the destination exists, it must match the source in type. +// If the destination is a directory, the directory must be empty. +// +// Returns a negative error code on failure. +int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath); + +// Find info about a file or directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a negative error code on failure. +int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info); + +// Get a custom attribute +// +// Custom attributes are uniquely identified by an 8-bit type and limited +// to LFS2_ATTR_MAX bytes. When read, if the stored attribute is smaller than +// the buffer, it will be padded with zeros. If the stored attribute is larger, +// then it will be silently truncated. If no attribute is found, the error +// LFS2_ERR_NOATTR is returned and the buffer is filled with zeros. +// +// Returns the size of the attribute, or a negative error code on failure. +// Note, the returned size is the size of the attribute on disk, irrespective +// of the size of the buffer. This can be used to dynamically allocate a buffer +// or check for existance. +lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path, + uint8_t type, void *buffer, lfs2_size_t size); + +// Set custom attributes +// +// Custom attributes are uniquely identified by an 8-bit type and limited +// to LFS2_ATTR_MAX bytes. If an attribute is not found, it will be +// implicitly created. +// +// Returns a negative error code on failure. +int lfs2_setattr(lfs2_t *lfs2, const char *path, + uint8_t type, const void *buffer, lfs2_size_t size); + +// Removes a custom attribute +// +// If an attribute is not found, nothing happens. +// +// Returns a negative error code on failure. +int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type); + + +/// File operations /// + +// Open a file +// +// The mode that the file is opened in is determined by the flags, which +// are values from the enum lfs2_open_flags that are bitwise-ored together. +// +// Returns a negative error code on failure. +int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, + const char *path, int flags); + +// Open a file with extra configuration +// +// The mode that the file is opened in is determined by the flags, which +// are values from the enum lfs2_open_flags that are bitwise-ored together. +// +// The config struct provides additional config options per file as described +// above. The config struct must be allocated while the file is open, and the +// config struct must be zeroed for defaults and backwards compatibility. +// +// Returns a negative error code on failure. +int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file, + const char *path, int flags, + const struct lfs2_file_config *config); + +// Close a file +// +// Any pending writes are written out to storage as though +// sync had been called and releases any allocated resources. +// +// Returns a negative error code on failure. +int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file); + +// Synchronize a file on storage +// +// Any pending writes are written out to storage. +// Returns a negative error code on failure. +int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file); + +// Read data from file +// +// Takes a buffer and size indicating where to store the read data. +// Returns the number of bytes read, or a negative error code on failure. +lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file, + void *buffer, lfs2_size_t size); + +// Write data to file +// +// Takes a buffer and size indicating the data to write. The file will not +// actually be updated on the storage until either sync or close is called. +// +// Returns the number of bytes written, or a negative error code on failure. +lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file, + const void *buffer, lfs2_size_t size); + +// Change the position of the file +// +// The change in position is determined by the offset and whence flag. +// Returns the new position of the file, or a negative error code on failure. +lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file, + lfs2_soff_t off, int whence); + +// Truncates the size of the file to the specified size +// +// Returns a negative error code on failure. +int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size); + +// Return the position of the file +// +// Equivalent to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_CUR) +// Returns the position of the file, or a negative error code on failure. +lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file); + +// Change the position of the file to the beginning of the file +// +// Equivalent to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_SET) +// Returns a negative error code on failure. +int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file); + +// Return the size of the file +// +// Similar to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_END) +// Returns the size of the file, or a negative error code on failure. +lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file); + + +/// Directory operations /// + +// Create a directory +// +// Returns a negative error code on failure. +int lfs2_mkdir(lfs2_t *lfs2, const char *path); + +// Open a directory +// +// Once open a directory can be used with read to iterate over files. +// Returns a negative error code on failure. +int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path); + +// Close a directory +// +// Releases any allocated resources. +// Returns a negative error code on failure. +int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir); + +// Read an entry in the directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a positive value on success, 0 at the end of directory, +// or a negative error code on failure. +int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info); + +// Change the position of the directory +// +// The new off must be a value previous returned from tell and specifies +// an absolute offset in the directory seek. +// +// Returns a negative error code on failure. +int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off); + +// Return the position of the directory +// +// The returned offset is only meant to be consumed by seek and may not make +// sense, but does indicate the current position in the directory iteration. +// +// Returns the position of the directory, or a negative error code on failure. +lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir); + +// Change the position of the directory to the beginning of the directory +// +// Returns a negative error code on failure. +int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir); + + +/// Filesystem-level filesystem operations + +// Finds the current size of the filesystem +// +// Note: Result is best effort. If files share COW structures, the returned +// size may be larger than the filesystem actually is. +// +// Returns the number of allocated blocks, or a negative error code on failure. +lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2); + +// Traverse through all blocks in use by the filesystem +// +// The provided callback will be called with each block address that is +// currently in use by the filesystem. This can be used to determine which +// blocks are in use or how much of the storage is available. +// +// Returns a negative error code on failure. +int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data); + +#ifdef LFS2_MIGRATE +// Attempts to migrate a previous version of littlefs +// +// Behaves similarly to the lfs2_format function. Attempts to mount +// the previous version of littlefs and update the filesystem so it can be +// mounted with the current version of littlefs. +// +// Requires a littlefs object and config struct. This clobbers the littlefs +// object, and does not leave the filesystem mounted. The config struct must +// be zeroed for defaults and backwards compatibility. +// +// Returns a negative error code on failure. +int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg); +#endif + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/lib/littlefs/lfs2_util.c b/lib/littlefs/lfs2_util.c new file mode 100644 index 0000000000000..083a99c36cf1e --- /dev/null +++ b/lib/littlefs/lfs2_util.c @@ -0,0 +1,33 @@ +/* + * lfs2 util functions + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "lfs2_util.h" + +// Only compile if user does not provide custom config +#ifndef LFS2_CONFIG + + +// Software CRC implementation with small lookup table +uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { + static const uint32_t rtable[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c, + }; + + const uint8_t *data = buffer; + + for (size_t i = 0; i < size; i++) { + crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf]; + crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf]; + } + + return crc; +} + + +#endif diff --git a/lib/littlefs/lfs2_util.h b/lib/littlefs/lfs2_util.h new file mode 100644 index 0000000000000..0f27073693e51 --- /dev/null +++ b/lib/littlefs/lfs2_util.h @@ -0,0 +1,230 @@ +/* + * lfs2 utility functions + * + * Copyright (c) 2017, Arm Limited. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LFS2_UTIL_H +#define LFS2_UTIL_H + +// Users can override lfs2_util.h with their own configuration by defining +// LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h). +// +// If LFS2_CONFIG is used, none of the default utils will be emitted and must be +// provided by the config file. To start, I would suggest copying lfs2_util.h +// and modifying as needed. +#ifdef LFS2_CONFIG +#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x) +#define LFS2_STRINGIZE2(x) #x +#include LFS2_STRINGIZE(LFS2_CONFIG) +#else + +// System includes +#include +#include +#include +#include + +#ifndef LFS2_NO_MALLOC +#include +#endif +#ifndef LFS2_NO_ASSERT +#include +#endif +#if !defined(LFS2_NO_DEBUG) || \ + !defined(LFS2_NO_WARN) || \ + !defined(LFS2_NO_ERROR) || \ + defined(LFS2_YES_TRACE) +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + + +// Macros, may be replaced by system specific wrappers. Arguments to these +// macros must not have side-effects as the macros can be removed for a smaller +// code footprint + +// Logging functions +#ifdef LFS2_YES_TRACE +#define LFS2_TRACE(fmt, ...) \ + printf("lfs2_trace:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS2_TRACE(fmt, ...) +#endif + +#ifndef LFS2_NO_DEBUG +#define LFS2_DEBUG(fmt, ...) \ + printf("lfs2_debug:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS2_DEBUG(fmt, ...) +#endif + +#ifndef LFS2_NO_WARN +#define LFS2_WARN(fmt, ...) \ + printf("lfs2_warn:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS2_WARN(fmt, ...) +#endif + +#ifndef LFS2_NO_ERROR +#define LFS2_ERROR(fmt, ...) \ + printf("lfs2_error:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS2_ERROR(fmt, ...) +#endif + +// Runtime assertions +#ifndef LFS2_NO_ASSERT +#define LFS2_ASSERT(test) assert(test) +#else +#define LFS2_ASSERT(test) +#endif + + +// Builtin functions, these may be replaced by more efficient +// toolchain-specific implementations. LFS2_NO_INTRINSICS falls back to a more +// expensive basic C implementation for debugging purposes + +// Min/max functions for unsigned 32-bit numbers +static inline uint32_t lfs2_max(uint32_t a, uint32_t b) { + return (a > b) ? a : b; +} + +static inline uint32_t lfs2_min(uint32_t a, uint32_t b) { + return (a < b) ? a : b; +} + +// Align to nearest multiple of a size +static inline uint32_t lfs2_aligndown(uint32_t a, uint32_t alignment) { + return a - (a % alignment); +} + +static inline uint32_t lfs2_alignup(uint32_t a, uint32_t alignment) { + return lfs2_aligndown(a + alignment-1, alignment); +} + +// Find the next smallest power of 2 less than or equal to a +static inline uint32_t lfs2_npw2(uint32_t a) { +#if !defined(LFS2_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return 32 - __builtin_clz(a-1); +#else + uint32_t r = 0; + uint32_t s; + a -= 1; + s = (a > 0xffff) << 4; a >>= s; r |= s; + s = (a > 0xff ) << 3; a >>= s; r |= s; + s = (a > 0xf ) << 2; a >>= s; r |= s; + s = (a > 0x3 ) << 1; a >>= s; r |= s; + return (r | (a >> 1)) + 1; +#endif +} + +// Count the number of trailing binary zeros in a +// lfs2_ctz(0) may be undefined +static inline uint32_t lfs2_ctz(uint32_t a) { +#if !defined(LFS2_NO_INTRINSICS) && defined(__GNUC__) + return __builtin_ctz(a); +#else + return lfs2_npw2((a & -a) + 1) - 1; +#endif +} + +// Count the number of binary ones in a +static inline uint32_t lfs2_popc(uint32_t a) { +#if !defined(LFS2_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return __builtin_popcount(a); +#else + a = a - ((a >> 1) & 0x55555555); + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); + return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; +#endif +} + +// Find the sequence comparison of a and b, this is the distance +// between a and b ignoring overflow +static inline int lfs2_scmp(uint32_t a, uint32_t b) { + return (int)(unsigned)(a - b); +} + +// Convert between 32-bit little-endian and native order +static inline uint32_t lfs2_fromle32(uint32_t a) { +#if !defined(LFS2_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + return a; +#elif !defined(LFS2_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + return __builtin_bswap32(a); +#else + return (((uint8_t*)&a)[0] << 0) | + (((uint8_t*)&a)[1] << 8) | + (((uint8_t*)&a)[2] << 16) | + (((uint8_t*)&a)[3] << 24); +#endif +} + +static inline uint32_t lfs2_tole32(uint32_t a) { + return lfs2_fromle32(a); +} + +// Convert between 32-bit big-endian and native order +static inline uint32_t lfs2_frombe32(uint32_t a) { +#if !defined(LFS2_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + return __builtin_bswap32(a); +#elif !defined(LFS2_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + return a; +#else + return (((uint8_t*)&a)[0] << 24) | + (((uint8_t*)&a)[1] << 16) | + (((uint8_t*)&a)[2] << 8) | + (((uint8_t*)&a)[3] << 0); +#endif +} + +static inline uint32_t lfs2_tobe32(uint32_t a) { + return lfs2_frombe32(a); +} + +// Calculate CRC-32 with polynomial = 0x04c11db7 +uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size); + +// Allocate memory, only used if buffers are not provided to littlefs +// Note, memory must be 64-bit aligned +static inline void *lfs2_malloc(size_t size) { +#ifndef LFS2_NO_MALLOC + return malloc(size); +#else + (void)size; + return NULL; +#endif +} + +// Deallocate memory, only used if buffers are not provided to littlefs +static inline void lfs2_free(void *p) { +#ifndef LFS2_NO_MALLOC + free(p); +#else + (void)p; +#endif +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif +#endif From 22bfc47977ac51b092765173de4cd01f731712cf Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 27 Oct 2019 18:37:24 +1100 Subject: [PATCH 0630/1299] lib/littlefs: Add README describing origin and how to gen lfs1/lfs2. --- lib/littlefs/README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 lib/littlefs/README.md diff --git a/lib/littlefs/README.md b/lib/littlefs/README.md new file mode 100644 index 0000000000000..1f0aacbf9840f --- /dev/null +++ b/lib/littlefs/README.md @@ -0,0 +1,19 @@ +littlefs library +================ + +The upstream source for the files in this directory is +https://github.com/ARMmbed/littlefs + +To generate the separate files with lfs1 and lfs2 prefixes run the following +commands in the top-level directory of the littlefs repository (replace the +version tags with the latest/desired ones, and set `$MPY_DIR`): + + git checkout v1.7.2 + python2 ./scripts/prefix.py lfs1 + cp lfs1*.[ch] $MPY_DIR/lib/littlefs + git reset --hard HEAD + + git checkout v2.1.3 + python2 ./scripts/prefix.py lfs2 + cp lfs2*.[ch] $MPY_DIR/lib/littlefs + git reset --hard HEAD From 98beea9cedca522857d12a741ff8ea90f6b873a3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 21 Oct 2019 19:08:04 +1100 Subject: [PATCH 0631/1299] extmod/vfs_blockdev: Add extended read/write methods. This commit adds helper functions to call readblocks/writeblocks with a fourth argument, the byte offset within a block. Although the mp_vfs_blockdev_t struct has grown here by 2 machine words, in all current uses of this struct within this repository it still fits within the same number of GC blocks. --- extmod/vfs.h | 6 ++++-- extmod/vfs_blockdev.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/extmod/vfs.h b/extmod/vfs.h index e626a14df0cc5..767ba3033a1c7 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -59,8 +59,8 @@ typedef struct _mp_vfs_proto_t { typedef struct _mp_vfs_blockdev_t { uint16_t flags; size_t block_size; - mp_obj_t readblocks[4]; - mp_obj_t writeblocks[4]; + mp_obj_t readblocks[5]; + mp_obj_t writeblocks[5]; // new protocol uses just ioctl, old uses sync (optional) and count union { mp_obj_t ioctl[4]; @@ -80,7 +80,9 @@ typedef struct _mp_vfs_mount_t { void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev); int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf); +int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf); int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf); +int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, const uint8_t *buf); mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg); mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out); diff --git a/extmod/vfs_blockdev.c b/extmod/vfs_blockdev.c index 0bc0fdebfa211..916d71ca47f70 100644 --- a/extmod/vfs_blockdev.c +++ b/extmod/vfs_blockdev.c @@ -60,6 +60,19 @@ int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_b } } +int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) { + mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf}; + self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); + self->readblocks[3] = MP_OBJ_FROM_PTR(&ar); + self->readblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off); + mp_obj_t ret = mp_call_method_n_kw(3, 0, self->readblocks); + if (ret == mp_const_none) { + return 0; + } else { + return MP_OBJ_SMALL_INT_VALUE(ret); + } +} + int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) { if (self->writeblocks[0] == MP_OBJ_NULL) { // read-only block device @@ -79,6 +92,24 @@ int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_ } } +int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, const uint8_t *buf) { + if (self->writeblocks[0] == MP_OBJ_NULL) { + // read-only block device + return -MP_EROFS; + } + + mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, (void*)buf}; + self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); + self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); + self->writeblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off); + mp_obj_t ret = mp_call_method_n_kw(3, 0, self->writeblocks); + if (ret == mp_const_none) { + return 0; + } else { + return MP_OBJ_SMALL_INT_VALUE(ret); + } +} + mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) { if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) { // New protocol with ioctl From a099505420221790509ab92611db52d0131e401a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 17:25:08 +1100 Subject: [PATCH 0632/1299] extmod: Add VFS littlefs bindings. Both LFS1 and LFS2 are supported at the same time. --- extmod/extmod.mk | 16 ++ extmod/vfs_lfs.c | 117 +++++++++++ extmod/vfs_lfs.h | 39 ++++ extmod/vfs_lfsx.c | 428 +++++++++++++++++++++++++++++++++++++++++ extmod/vfs_lfsx_file.c | 236 +++++++++++++++++++++++ py/py.mk | 1 + 6 files changed, 837 insertions(+) create mode 100644 extmod/vfs_lfs.c create mode 100644 extmod/vfs_lfs.h create mode 100644 extmod/vfs_lfsx.c create mode 100644 extmod/vfs_lfsx_file.c diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 05d0be3b1675c..8e63b25f9081c 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -3,6 +3,22 @@ # this sets the config file for FatFs CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" +################################################################################ +# VFS littlefs + +ifeq ($(MICROPY_VFS_LFS),1) +CFLAGS_MOD += -DMICROPY_VFS_LFS=1 +CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT +CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT +LITTLEFS_DIR = lib/littlefs +SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ + lfs1.c \ + lfs1_util.c \ + lfs2.c \ + lfs2_util.c \ + ) +endif + ################################################################################ # ussl diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c new file mode 100644 index 0000000000000..72f501abbf42a --- /dev/null +++ b/extmod/vfs_lfs.c @@ -0,0 +1,117 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "extmod/vfs.h" +#include "extmod/vfs_lfs.h" + +#if MICROPY_VFS && MICROPY_VFS_LFS + +enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead }; + +static const mp_arg_t lfs_make_allowed_args[] = { + { MP_QSTR_, MP_ARG_OBJ }, + { MP_QSTR_readsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, + { MP_QSTR_progsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, + { MP_QSTR_lookahead, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, +}; + +#include "lib/littlefs/lfs1.h" + +#define LFS_BUILD_VERSION (1) +#define LFSx_MACRO(s) LFS1 ## s +#define LFSx_API(s) lfs1_ ## s +#define MP_VFS_LFSx(s) mp_vfs_lfs1_ ## s +#define MP_OBJ_VFS_LFSx mp_obj_vfs_lfs1_t +#define MP_OBJ_VFS_LFSx_FILE mp_obj_vfs_lfs1_file_t +#define MP_TYPE_VFS_LFSx mp_type_vfs_lfs1 +#define MP_TYPE_VFS_LFSx_(s) mp_type_vfs_lfs1 ## s + +typedef struct _mp_obj_vfs_lfs1_t { + mp_obj_base_t base; + mp_vfs_blockdev_t blockdev; + vstr_t cur_dir; + struct lfs1_config config; + lfs1_t lfs; +} mp_obj_vfs_lfs1_t; + +typedef struct _mp_obj_vfs_lfs1_file_t { + mp_obj_base_t base; + mp_obj_vfs_lfs1_t *vfs; + lfs1_file_t file; + struct lfs1_file_config cfg; + uint8_t file_buffer[0]; +} mp_obj_vfs_lfs1_file_t; + +const char *mp_vfs_lfs1_make_path(mp_obj_vfs_lfs1_t *self, mp_obj_t path_in); +mp_obj_t mp_vfs_lfs1_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in); + +#include "extmod/vfs_lfsx.c" +#include "extmod/vfs_lfsx_file.c" + +#undef LFS_BUILD_VERSION +#undef LFSx_MACRO +#undef LFSx_API +#undef MP_VFS_LFSx +#undef MP_OBJ_VFS_LFSx +#undef MP_OBJ_VFS_LFSx_FILE +#undef MP_TYPE_VFS_LFSx +#undef MP_TYPE_VFS_LFSx_ + +#include "lib/littlefs/lfs2.h" + +#define LFS_BUILD_VERSION (2) +#define LFSx_MACRO(s) LFS2 ## s +#define LFSx_API(s) lfs2_ ## s +#define MP_VFS_LFSx(s) mp_vfs_lfs2_ ## s +#define MP_OBJ_VFS_LFSx mp_obj_vfs_lfs2_t +#define MP_OBJ_VFS_LFSx_FILE mp_obj_vfs_lfs2_file_t +#define MP_TYPE_VFS_LFSx mp_type_vfs_lfs2 +#define MP_TYPE_VFS_LFSx_(s) mp_type_vfs_lfs2 ## s + +typedef struct _mp_obj_vfs_lfs2_t { + mp_obj_base_t base; + mp_vfs_blockdev_t blockdev; + vstr_t cur_dir; + struct lfs2_config config; + lfs2_t lfs; +} mp_obj_vfs_lfs2_t; + +typedef struct _mp_obj_vfs_lfs2_file_t { + mp_obj_base_t base; + mp_obj_vfs_lfs2_t *vfs; + lfs2_file_t file; + struct lfs2_file_config cfg; + uint8_t file_buffer[0]; +} mp_obj_vfs_lfs2_file_t; + +const char *mp_vfs_lfs2_make_path(mp_obj_vfs_lfs2_t *self, mp_obj_t path_in); +mp_obj_t mp_vfs_lfs2_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in); + +#include "extmod/vfs_lfsx.c" +#include "extmod/vfs_lfsx_file.c" + +#endif // MICROPY_VFS && MICROPY_VFS_LFS diff --git a/extmod/vfs_lfs.h b/extmod/vfs_lfs.h new file mode 100644 index 0000000000000..1fdf792f1b3bc --- /dev/null +++ b/extmod/vfs_lfs.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_EXTMOD_VFS_LFS_H +#define MICROPY_INCLUDED_EXTMOD_VFS_LFS_H + +#include "py/obj.h" + +extern const mp_obj_type_t mp_type_vfs_lfs1; +extern const mp_obj_type_t mp_type_vfs_lfs1_fileio; +extern const mp_obj_type_t mp_type_vfs_lfs1_textio; + +extern const mp_obj_type_t mp_type_vfs_lfs2; +extern const mp_obj_type_t mp_type_vfs_lfs2_fileio; +extern const mp_obj_type_t mp_type_vfs_lfs2_textio; + +#endif // MICROPY_INCLUDED_EXTMOD_VFS_LFS_H diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c new file mode 100644 index 0000000000000..a042f5ed1eaea --- /dev/null +++ b/extmod/vfs_lfsx.c @@ -0,0 +1,428 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/runtime.h" +#include "py/stream.h" +#include "py/binary.h" +#include "py/objarray.h" +#include "py/mperrno.h" +#include "extmod/vfs.h" + +STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API(config) *c, int cmd, int arg, bool must_return_int) { + mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg); + int ret_i = 0; + if (must_return_int || ret != mp_const_none) { + ret_i = mp_obj_get_int(ret); + } + return ret_i; +} + +STATIC int MP_VFS_LFSx(dev_read)(const struct LFSx_API(config) *c, LFSx_API(block_t) block, LFSx_API(off_t) off, void *buffer, LFSx_API(size_t) size) { + return mp_vfs_blockdev_read_ext(c->context, block, off, size, buffer); +} + +STATIC int MP_VFS_LFSx(dev_prog)(const struct LFSx_API(config) *c, LFSx_API(block_t) block, LFSx_API(off_t) off, const void *buffer, LFSx_API(size_t) size) { + return mp_vfs_blockdev_write_ext(c->context, block, off, size, buffer); +} + +STATIC int MP_VFS_LFSx(dev_erase)(const struct LFSx_API(config) *c, LFSx_API(block_t) block) { + return MP_VFS_LFSx(dev_ioctl)(c, 6, block, true); // erase +} + +STATIC int MP_VFS_LFSx(dev_sync)(const struct LFSx_API(config) *c) { + return MP_VFS_LFSx(dev_ioctl)(c, BP_IOCTL_SYNC, 0, false); +} + +STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx *self, mp_obj_t bdev, size_t read_size, size_t prog_size, size_t lookahead) { + self->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; + mp_vfs_blockdev_init(&self->blockdev, bdev); + + struct LFSx_API(config) *config = &self->config; + memset(config, 0, sizeof(*config)); + + config->context = &self->blockdev; + + config->read = MP_VFS_LFSx(dev_read); + config->prog = MP_VFS_LFSx(dev_prog); + config->erase = MP_VFS_LFSx(dev_erase); + config->sync = MP_VFS_LFSx(dev_sync); + + MP_VFS_LFSx(dev_ioctl)(config, BP_IOCTL_INIT, 0, false); // initialise block device + int bs = MP_VFS_LFSx(dev_ioctl)(config, BP_IOCTL_SEC_SIZE, 0, true); // get block size + int bc = MP_VFS_LFSx(dev_ioctl)(config, BP_IOCTL_SEC_COUNT, 0, true); // get block count + self->blockdev.block_size = bs; + + config->read_size = read_size; + config->prog_size = prog_size; + config->block_size = bs; + config->block_count = bc; + + #if LFS_BUILD_VERSION == 1 + config->lookahead = lookahead; + config->read_buffer = m_new(uint8_t, config->read_size); + config->prog_buffer = m_new(uint8_t, config->prog_size); + config->lookahead_buffer = m_new(uint8_t, config->lookahead / 8); + #else + config->block_cycles = 100; + config->cache_size = 4 * MAX(read_size, prog_size); + config->lookahead_size = lookahead; + config->read_buffer = m_new(uint8_t, config->cache_size); + config->prog_buffer = m_new(uint8_t, config->cache_size); + config->lookahead_buffer = m_new(uint8_t, config->lookahead_size); + #endif +} + +const char *MP_VFS_LFSx(make_path)(MP_OBJ_VFS_LFSx *self, mp_obj_t path_in) { + const char *path = mp_obj_str_get_str(path_in); + if (path[0] != '/') { + size_t l = vstr_len(&self->cur_dir); + if (l > 0) { + vstr_add_str(&self->cur_dir, path); + path = vstr_null_terminated_str(&self->cur_dir); + self->cur_dir.len = l; + } + } + return path; +} + +STATIC mp_obj_t MP_VFS_LFSx(make_new)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + mp_arg_val_t args[MP_ARRAY_SIZE(lfs_make_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(lfs_make_allowed_args), lfs_make_allowed_args, args); + + MP_OBJ_VFS_LFSx *self = m_new0(MP_OBJ_VFS_LFSx, 1); + self->base.type = type; + vstr_init(&self->cur_dir, 16); + vstr_add_byte(&self->cur_dir, '/'); + MP_VFS_LFSx(init_config)(self, args[LFS_MAKE_ARG_bdev].u_obj, + args[LFS_MAKE_ARG_readsize].u_int, args[LFS_MAKE_ARG_progsize].u_int, args[LFS_MAKE_ARG_lookahead].u_int); + int ret = LFSx_API(mount)(&self->lfs, &self->config); + if (ret < 0) { + mp_raise_OSError(-ret); + } + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t MP_VFS_LFSx(mkfs)(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_arg_val_t args[MP_ARRAY_SIZE(lfs_make_allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(lfs_make_allowed_args), lfs_make_allowed_args, args); + + MP_OBJ_VFS_LFSx self; + MP_VFS_LFSx(init_config)(&self, args[LFS_MAKE_ARG_bdev].u_obj, + args[LFS_MAKE_ARG_readsize].u_int, args[LFS_MAKE_ARG_progsize].u_int, args[LFS_MAKE_ARG_lookahead].u_int); + int ret = LFSx_API(format)(&self.lfs, &self.config); + if (ret < 0) { + mp_raise_OSError(-ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(MP_VFS_LFSx(mkfs_fun_obj), 0, MP_VFS_LFSx(mkfs)); +STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(MP_VFS_LFSx(mkfs_obj), MP_ROM_PTR(&MP_VFS_LFSx(mkfs_fun_obj))); + +// Implementation of mp_vfs_lfs_file_open is provided in vfs_lfsx_file.c +STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open)); + +typedef struct MP_VFS_LFSx(_ilistdir_it_t) { + mp_obj_base_t base; + mp_fun_1_t iternext; + bool is_str; + MP_OBJ_VFS_LFSx *vfs; + LFSx_API(dir_t) dir; +} MP_VFS_LFSx(ilistdir_it_t); + +STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { + MP_VFS_LFSx(ilistdir_it_t) *self = MP_OBJ_TO_PTR(self_in); + + struct LFSx_API(info) info; + for (;;) { + int ret = LFSx_API(dir_read)(&self->vfs->lfs, &self->dir, &info); + if (ret == 0) { + LFSx_API(dir_close)(&self->vfs->lfs, &self->dir); + return MP_OBJ_STOP_ITERATION; + } + if (!(info.name[0] == '.' && (info.name[1] == '\0' + || (info.name[1] == '.' && info.name[2] == '\0')))) { + break; + } + } + + // make 4-tuple with info about this entry + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); + if (self->is_str) { + t->items[0] = mp_obj_new_str(info.name, strlen(info.name)); + } else { + t->items[0] = mp_obj_new_bytes((const byte*)info.name, strlen(info.name)); + } + t->items[1] = MP_OBJ_NEW_SMALL_INT(info.type == LFSx_MACRO(_TYPE_REG) ? MP_S_IFREG : MP_S_IFDIR); + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number + t->items[3] = MP_OBJ_NEW_SMALL_INT(info.size); + + return MP_OBJ_FROM_PTR(t); +} + +STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(args[0]); + bool is_str_type = true; + const char *path; + if (n_args == 2) { + if (mp_obj_get_type(args[1]) == &mp_type_bytes) { + is_str_type = false; + } + path = MP_VFS_LFSx(make_path)(self, args[1]); + } else { + path = vstr_null_terminated_str(&self->cur_dir); + } + + MP_VFS_LFSx(ilistdir_it_t) *iter = m_new_obj(MP_VFS_LFSx(ilistdir_it_t)); + iter->base.type = &mp_type_polymorph_iter; + iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext); + iter->is_str = is_str_type; + iter->vfs = self; + int ret = LFSx_API(dir_open)(&self->lfs, &iter->dir, path); + if (ret < 0) { + mp_raise_OSError(-ret); + } + return MP_OBJ_FROM_PTR(iter); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func)); + +STATIC mp_obj_t MP_VFS_LFSx(remove)(mp_obj_t self_in, mp_obj_t path_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + const char *path = MP_VFS_LFSx(make_path)(self, path_in); + int ret = LFSx_API(remove)(&self->lfs, path); + if (ret < 0) { + mp_raise_OSError(-ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(remove_obj), MP_VFS_LFSx(remove)); + +STATIC mp_obj_t MP_VFS_LFSx(rmdir)(mp_obj_t self_in, mp_obj_t path_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + const char *path = MP_VFS_LFSx(make_path)(self, path_in); + int ret = LFSx_API(remove)(&self->lfs, path); + if (ret < 0) { + mp_raise_OSError(-ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(rmdir_obj), MP_VFS_LFSx(rmdir)); + +STATIC mp_obj_t MP_VFS_LFSx(rename)(mp_obj_t self_in, mp_obj_t path_old_in, mp_obj_t path_new_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + const char *path_old = MP_VFS_LFSx(make_path)(self, path_old_in); + vstr_t path_new; + vstr_init(&path_new, vstr_len(&self->cur_dir)); + vstr_add_strn(&path_new, vstr_str(&self->cur_dir), vstr_len(&self->cur_dir)); + vstr_add_str(&path_new, mp_obj_str_get_str(path_new_in)); + int ret = LFSx_API(rename)(&self->lfs, path_old, vstr_null_terminated_str(&path_new)); + vstr_clear(&path_new); + if (ret < 0) { + mp_raise_OSError(-ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(rename_obj), MP_VFS_LFSx(rename)); + +STATIC mp_obj_t MP_VFS_LFSx(mkdir)(mp_obj_t self_in, mp_obj_t path_o) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + const char *path = MP_VFS_LFSx(make_path)(self, path_o); + int ret = LFSx_API(mkdir)(&self->lfs, path); + if (ret < 0) { + mp_raise_OSError(-ret); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(mkdir_obj), MP_VFS_LFSx(mkdir)); + +STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + + // Check path exists + const char *path = MP_VFS_LFSx(make_path)(self, path_in); + if (path[1] != '\0') { + // Not at root, check it exists + struct LFSx_API(info) info; + int ret = LFSx_API(stat)(&self->lfs, path, &info); + if (ret < 0 || info.type != LFSx_MACRO(_TYPE_DIR)) { + mp_raise_OSError(-MP_ENOENT); + } + } + + // Update cur_dir with new path + if (path == vstr_str(&self->cur_dir)) { + self->cur_dir.len = strlen(path); + } else { + vstr_reset(&self->cur_dir); + vstr_add_str(&self->cur_dir, path); + } + + // If not at root add trailing / to make it easy to build paths + if (vstr_len(&self->cur_dir) != 1) { + vstr_add_byte(&self->cur_dir, '/'); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(chdir_obj), MP_VFS_LFSx(chdir)); + +STATIC mp_obj_t MP_VFS_LFSx(getcwd)(mp_obj_t self_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + if (vstr_len(&self->cur_dir) == 1) { + return MP_OBJ_NEW_QSTR(MP_QSTR__slash_); + } else { + // don't include trailing / + return mp_obj_new_str(self->cur_dir.buf, self->cur_dir.len - 1); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(getcwd_obj), MP_VFS_LFSx(getcwd)); + +STATIC mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + const char *path = mp_obj_str_get_str(path_in); + struct LFSx_API(info) info; + int ret = LFSx_API(stat)(&self->lfs, path, &info); + if (ret < 0) { + mp_raise_OSError(-ret); + } + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(info.type == LFSx_MACRO(_TYPE_REG) ? MP_S_IFREG : MP_S_IFDIR); // st_mode + t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev + t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink + t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid + t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid + t->items[6] = mp_obj_new_int_from_uint(info.size); // st_size + t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // st_atime + t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // st_mtime + t->items[9] = MP_OBJ_NEW_SMALL_INT(0); // st_ctime + + return MP_OBJ_FROM_PTR(t); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(stat_obj), MP_VFS_LFSx(stat)); + +STATIC int LFSx_API(traverse_cb)(void *data, LFSx_API(block_t) bl) { + (void)bl; + uint32_t *n = (uint32_t*)data; + *n += 1; + return LFSx_MACRO(_ERR_OK); +} + +STATIC mp_obj_t MP_VFS_LFSx(statvfs)(mp_obj_t self_in, mp_obj_t path_in) { + (void)path_in; + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + uint32_t n_used_blocks = 0; + #if LFS_BUILD_VERSION == 1 + int ret = LFSx_API(traverse)(&self->lfs, LFSx_API(traverse_cb), &n_used_blocks); + #else + int ret = LFSx_API(fs_traverse)(&self->lfs, LFSx_API(traverse_cb), &n_used_blocks); + #endif + if (ret < 0) { + mp_raise_OSError(-ret); + } + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(self->lfs.cfg->block_size); // f_bsize + t->items[1] = t->items[0]; // f_frsize + t->items[2] = MP_OBJ_NEW_SMALL_INT(self->lfs.cfg->block_count); // f_blocks + t->items[3] = MP_OBJ_NEW_SMALL_INT(self->lfs.cfg->block_count - n_used_blocks); // f_bfree + t->items[4] = t->items[3]; // f_bavail + t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files + t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree + t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail + t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags + t->items[9] = MP_OBJ_NEW_SMALL_INT(LFSx_MACRO(_NAME_MAX)); // f_namemax + + return MP_OBJ_FROM_PTR(t); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(statvfs_obj), MP_VFS_LFSx(statvfs)); + +STATIC mp_obj_t MP_VFS_LFSx(mount)(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { + (void)self_in; + (void)readonly; + (void)mkfs; + // already called LFSx_API(mount) in MP_VFS_LFSx(make_new) + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(mount_obj), MP_VFS_LFSx(mount)); + +STATIC mp_obj_t MP_VFS_LFSx(umount)(mp_obj_t self_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + // LFS unmount never fails + LFSx_API(unmount)(&self->lfs); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(umount_obj), MP_VFS_LFSx(umount)); + +STATIC const mp_rom_map_elem_t MP_VFS_LFSx(locals_dict_table)[] = { + { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&MP_VFS_LFSx(mkfs_obj)) }, + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&MP_VFS_LFSx(open_obj)) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&MP_VFS_LFSx(ilistdir_obj)) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&MP_VFS_LFSx(mkdir_obj)) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&MP_VFS_LFSx(rmdir_obj)) }, + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&MP_VFS_LFSx(chdir_obj)) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&MP_VFS_LFSx(getcwd_obj)) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&MP_VFS_LFSx(remove_obj)) }, + { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&MP_VFS_LFSx(rename_obj)) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&MP_VFS_LFSx(stat_obj)) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&MP_VFS_LFSx(statvfs_obj)) }, + { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&MP_VFS_LFSx(mount_obj)) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&MP_VFS_LFSx(umount_obj)) }, +}; +STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(locals_dict), MP_VFS_LFSx(locals_dict_table)); + +STATIC mp_import_stat_t MP_VFS_LFSx(import_stat)(void *self_in, const char *path) { + MP_OBJ_VFS_LFSx *self = self_in; + struct LFSx_API(info) info; + int ret = LFSx_API(stat)(&self->lfs, path, &info); + if (ret == 0) { + if (info.type == LFSx_MACRO(_TYPE_REG)) { + return MP_IMPORT_STAT_FILE; + } else { + return MP_IMPORT_STAT_DIR; + } + } + return MP_IMPORT_STAT_NO_EXIST; +} + +STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = { + .import_stat = MP_VFS_LFSx(import_stat), +}; + +const mp_obj_type_t MP_TYPE_VFS_LFSx = { + { &mp_type_type }, + #if LFS_BUILD_VERSION == 1 + .name = MP_QSTR_VfsLfs1, + #else + .name = MP_QSTR_VfsLfs2, + #endif + .make_new = MP_VFS_LFSx(make_new), + .protocol = &MP_VFS_LFSx(proto), + .locals_dict = (mp_obj_dict_t*)&MP_VFS_LFSx(locals_dict), +}; diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c new file mode 100644 index 0000000000000..113c3ec990c86 --- /dev/null +++ b/extmod/vfs_lfsx_file.c @@ -0,0 +1,236 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "extmod/vfs.h" + +STATIC void MP_VFS_LFSx(check_open)(MP_OBJ_VFS_LFSx_FILE *self) { + if (self->vfs == NULL) { + mp_raise_ValueError(NULL); + } +} + +STATIC void MP_VFS_LFSx(file_print)(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)self_in; + (void)kind; + mp_printf(print, "", mp_obj_get_type_str(self_in)); +} + +mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { + MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); + + int flags = 0; + const mp_obj_type_t *type = &MP_TYPE_VFS_LFSx_(_textio); + const char *mode_str = mp_obj_str_get_str(mode_in); + for (; *mode_str; ++mode_str) { + int new_flags = 0; + switch (*mode_str) { + case 'r': + new_flags = LFSx_MACRO(_O_RDONLY); + break; + case 'w': + new_flags = LFSx_MACRO(_O_WRONLY) | LFSx_MACRO(_O_CREAT) | LFSx_MACRO(_O_TRUNC); + break; + case 'x': + new_flags = LFSx_MACRO(_O_WRONLY) | LFSx_MACRO(_O_CREAT) | LFSx_MACRO(_O_EXCL); + break; + case 'a': + new_flags = LFSx_MACRO(_O_WRONLY) | LFSx_MACRO(_O_CREAT) | LFSx_MACRO(_O_APPEND); + break; + case '+': + flags |= LFSx_MACRO(_O_RDWR); + break; + #if MICROPY_PY_IO_FILEIO + case 'b': + type = &MP_TYPE_VFS_LFSx_(_fileio); + break; + #endif + case 't': + type = &MP_TYPE_VFS_LFSx_(_textio); + break; + } + if (new_flags) { + if (flags) { + mp_raise_ValueError(NULL); + } + flags = new_flags; + } + } + if (flags == 0) { + flags = LFSx_MACRO(_O_RDONLY); + } + + #if LFS_BUILD_VERSION == 1 + MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->prog_size); + #else + MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->cache_size); + #endif + o->base.type = type; + o->vfs = self; + #if !MICROPY_GC_CONSERVATIVE_CLEAR + memset(&o->file, 0, sizeof(o->file)); + memset(&o->cfg, 0, sizeof(o->cfg)); + #endif + o->cfg.buffer = &o->file_buffer[0]; + + const char *path = MP_VFS_LFSx(make_path)(self, path_in); + int ret = LFSx_API(file_opencfg)(&self->lfs, &o->file, path, flags, &o->cfg); + if (ret < 0) { + o->vfs = NULL; + mp_raise_OSError(-ret); + } + + return MP_OBJ_FROM_PTR(o); +} + +STATIC mp_obj_t MP_VFS_LFSx(file___exit__)(size_t n_args, const mp_obj_t *args) { + (void)n_args; + return mp_stream_close(args[0]); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(file___exit___obj), 4, 4, MP_VFS_LFSx(file___exit__)); + +STATIC mp_uint_t MP_VFS_LFSx(file_read)(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { + MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); + MP_VFS_LFSx(check_open)(self); + LFSx_API(ssize_t) sz = LFSx_API(file_read)(&self->vfs->lfs, &self->file, buf, size); + if (sz < 0) { + *errcode = -sz; + return MP_STREAM_ERROR; + } + return sz; +} + +STATIC mp_uint_t MP_VFS_LFSx(file_write)(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { + MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); + MP_VFS_LFSx(check_open)(self); + LFSx_API(ssize_t) sz = LFSx_API(file_write)(&self->vfs->lfs, &self->file, buf, size); + if (sz < 0) { + *errcode = -sz; + return MP_STREAM_ERROR; + } + return sz; +} + +STATIC mp_uint_t MP_VFS_LFSx(file_ioctl)(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); + + if (request != MP_STREAM_CLOSE) { + MP_VFS_LFSx(check_open)(self); + } + + if (request == MP_STREAM_SEEK) { + struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)(uintptr_t)arg; + int res = LFSx_API(file_seek)(&self->vfs->lfs, &self->file, s->offset, s->whence); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + res = LFSx_API(file_tell)(&self->vfs->lfs, &self->file); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + s->offset = res; + return 0; + } else if (request == MP_STREAM_FLUSH) { + int res = LFSx_API(file_sync)(&self->vfs->lfs, &self->file); + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return 0; + } else if (request == MP_STREAM_CLOSE) { + if (self->vfs == NULL) { + return 0; + } + int res = LFSx_API(file_close)(&self->vfs->lfs, &self->file); + self->vfs = NULL; // indicate a closed file + if (res < 0) { + *errcode = -res; + return MP_STREAM_ERROR; + } + return 0; + } else { + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } +} + +STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, + { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&MP_VFS_LFSx(file___exit___obj)) }, +}; +STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table)); + +#if MICROPY_PY_IO_FILEIO +STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { + .read = MP_VFS_LFSx(file_read), + .write = MP_VFS_LFSx(file_write), + .ioctl = MP_VFS_LFSx(file_ioctl), +}; + +const mp_obj_type_t MP_TYPE_VFS_LFSx_(_fileio) = { + { &mp_type_type }, + .name = MP_QSTR_FileIO, + .print = MP_VFS_LFSx(file_print), + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &MP_VFS_LFSx(fileio_stream_p), + .locals_dict = (mp_obj_dict_t*)&MP_VFS_LFSx(file_locals_dict), +}; +#endif + +STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { + .read = MP_VFS_LFSx(file_read), + .write = MP_VFS_LFSx(file_write), + .ioctl = MP_VFS_LFSx(file_ioctl), + .is_text = true, +}; + +const mp_obj_type_t MP_TYPE_VFS_LFSx_(_textio) = { + { &mp_type_type }, + .name = MP_QSTR_TextIOWrapper, + .print = MP_VFS_LFSx(file_print), + .getiter = mp_identity_getiter, + .iternext = mp_stream_unbuffered_iter, + .protocol = &MP_VFS_LFSx(textio_stream_p), + .locals_dict = (mp_obj_dict_t*)&MP_VFS_LFSx(file_locals_dict), +}; diff --git a/py/py.mk b/py/py.mk index b08b3f80c8418..8c2d3c7b80cc6 100644 --- a/py/py.mk +++ b/py/py.mk @@ -192,6 +192,7 @@ PY_EXTMOD_O_BASENAME = \ extmod/vfs_fat.o \ extmod/vfs_fat_diskio.o \ extmod/vfs_fat_file.o \ + extmod/vfs_lfs.o \ extmod/utime_mphal.o \ extmod/uos_dupterm.o \ lib/embed/abort_.o \ From 62d5659cdd198cf88ed9ac5a2b0aadb03a8098cb Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 17:25:21 +1100 Subject: [PATCH 0633/1299] unix: Enable uos.VfsLfs1, uos.VfsLfs2 on coverage build. --- ports/unix/Makefile | 1 + ports/unix/moduos_vfs.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index bcc76ce160250..5a21bd6b2a050 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -257,6 +257,7 @@ coverage: -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ -DMICROPY_UNIX_COVERAGE' \ LDFLAGS_EXTRA='-fprofile-arcs -ftest-coverage' \ + MICROPY_VFS_LFS=1 \ FROZEN_MANIFEST=manifest_coverage.py \ BUILD=build-coverage PROG=micropython_coverage diff --git a/ports/unix/moduos_vfs.c b/ports/unix/moduos_vfs.c index e9ac8e1f88244..7abd0d150bc7c 100644 --- a/ports/unix/moduos_vfs.c +++ b/ports/unix/moduos_vfs.c @@ -30,6 +30,7 @@ #include "extmod/vfs.h" #include "extmod/vfs_posix.h" #include "extmod/vfs_fat.h" +#include "extmod/vfs_lfs.h" #if MICROPY_VFS @@ -71,6 +72,10 @@ STATIC const mp_rom_map_elem_t uos_vfs_module_globals_table[] = { #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif + #if MICROPY_VFS_LFS + { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, + { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(uos_vfs_module_globals, uos_vfs_module_globals_table); From 73fddb84e5b2a313170e1286013b99f23430dbed Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 17:25:48 +1100 Subject: [PATCH 0634/1299] tests/extmod: Add littlefs tests. --- tests/extmod/vfs_lfs.py | 107 +++++++++++++++++++++++++ tests/extmod/vfs_lfs.py.exp | 46 +++++++++++ tests/extmod/vfs_lfs_corrupt.py | 106 +++++++++++++++++++++++++ tests/extmod/vfs_lfs_corrupt.py.exp | 12 +++ tests/extmod/vfs_lfs_error.py | 116 +++++++++++++++++++++++++++ tests/extmod/vfs_lfs_error.py.exp | 28 +++++++ tests/extmod/vfs_lfs_file.py | 117 ++++++++++++++++++++++++++++ tests/extmod/vfs_lfs_file.py.exp | 28 +++++++ tests/extmod/vfs_lfs_mount.py | 73 +++++++++++++++++ tests/extmod/vfs_lfs_mount.py.exp | 6 ++ 10 files changed, 639 insertions(+) create mode 100644 tests/extmod/vfs_lfs.py create mode 100644 tests/extmod/vfs_lfs.py.exp create mode 100644 tests/extmod/vfs_lfs_corrupt.py create mode 100644 tests/extmod/vfs_lfs_corrupt.py.exp create mode 100644 tests/extmod/vfs_lfs_error.py create mode 100644 tests/extmod/vfs_lfs_error.py.exp create mode 100644 tests/extmod/vfs_lfs_file.py create mode 100644 tests/extmod/vfs_lfs_file.py.exp create mode 100644 tests/extmod/vfs_lfs_mount.py create mode 100644 tests/extmod/vfs_lfs_mount.py.exp diff --git a/tests/extmod/vfs_lfs.py b/tests/extmod/vfs_lfs.py new file mode 100644 index 0000000000000..46c770b437ec5 --- /dev/null +++ b/tests/extmod/vfs_lfs.py @@ -0,0 +1,107 @@ +# Test for VfsLittle using a RAM device + +try: + import uos + uos.VfsLfs1 + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 1024 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + +def test(bdev, vfs_class): + print('test', vfs_class) + + # mkfs + vfs_class.mkfs(bdev) + + # construction + vfs = vfs_class(bdev) + + # statvfs + print(vfs.statvfs('/')) + + # open, write close + f = vfs.open('test', 'w') + f.write('littlefs') + f.close() + + # statvfs after creating a file + print(vfs.statvfs('/')) + + # ilistdir + print(list(vfs.ilistdir())) + print(list(vfs.ilistdir('/'))) + print(list(vfs.ilistdir(b'/'))) + + # mkdir, rmdir + vfs.mkdir('testdir') + print(list(vfs.ilistdir())) + print(list(vfs.ilistdir('testdir'))) + vfs.rmdir('testdir') + print(list(vfs.ilistdir())) + vfs.mkdir('testdir') + + # stat a file + print(vfs.stat('test')) + + # stat a dir (size seems to vary on LFS2 so don't print that) + print(vfs.stat('testdir')[:6]) + + # read + with vfs.open('test', 'r') as f: + print(f.read()) + + # create large file + with vfs.open('testbig', 'w') as f: + data = 'large012' * 32 * 16 + print('data length:', len(data)) + for i in range(4): + print('write', i) + f.write(data) + + # stat after creating large file + print(vfs.statvfs('/')) + + # rename + vfs.rename('testbig', 'testbig2') + print(list(vfs.ilistdir())) + + # remove + vfs.remove('testbig2') + print(list(vfs.ilistdir())) + + # getcwd, chdir + print(vfs.getcwd()) + vfs.chdir('/testdir') + print(vfs.getcwd()) + vfs.chdir('/') + print(vfs.getcwd()) + vfs.rmdir('testdir') + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsLfs1) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs.py.exp b/tests/extmod/vfs_lfs.py.exp new file mode 100644 index 0000000000000..c16e727b81904 --- /dev/null +++ b/tests/extmod/vfs_lfs.py.exp @@ -0,0 +1,46 @@ +test +(1024, 1024, 30, 26, 26, 0, 0, 0, 0, 255) +(1024, 1024, 30, 25, 25, 0, 0, 0, 0, 255) +[('test', 32768, 0, 8)] +[('test', 32768, 0, 8)] +[(b'test', 32768, 0, 8)] +[('test', 32768, 0, 8), ('testdir', 16384, 0, 0)] +[] +[('test', 32768, 0, 8)] +(32768, 0, 0, 0, 0, 0, 8, 0, 0, 0) +(16384, 0, 0, 0, 0, 0) +littlefs +data length: 4096 +write 0 +write 1 +write 2 +write 3 +(1024, 1024, 30, 6, 6, 0, 0, 0, 0, 255) +[('test', 32768, 0, 8), ('testdir', 16384, 0, 0), ('testbig2', 32768, 0, 16384)] +[('test', 32768, 0, 8), ('testdir', 16384, 0, 0)] +/ +/testdir +/ +test +(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255) +(1024, 1024, 30, 28, 28, 0, 0, 0, 0, 255) +[('test', 32768, 0, 8)] +[('test', 32768, 0, 8)] +[(b'test', 32768, 0, 8)] +[('testdir', 16384, 0, 0), ('test', 32768, 0, 8)] +[] +[('test', 32768, 0, 8)] +(32768, 0, 0, 0, 0, 0, 8, 0, 0, 0) +(16384, 0, 0, 0, 0, 0) +littlefs +data length: 4096 +write 0 +write 1 +write 2 +write 3 +(1024, 1024, 30, 9, 9, 0, 0, 0, 0, 255) +[('testbig2', 32768, 0, 16384), ('testdir', 16384, 0, 0), ('test', 32768, 0, 8)] +[('testdir', 16384, 0, 0), ('test', 32768, 0, 8)] +/ +/testdir +/ diff --git a/tests/extmod/vfs_lfs_corrupt.py b/tests/extmod/vfs_lfs_corrupt.py new file mode 100644 index 0000000000000..90c3e82163ddc --- /dev/null +++ b/tests/extmod/vfs_lfs_corrupt.py @@ -0,0 +1,106 @@ +# Test for VfsLittle using a RAM device, testing error handling from corrupt block device + +try: + import uos + uos.VfsLfs1 + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 1024 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + self.ret = 0 + + def readblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + return self.ret + + def writeblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + return self.ret + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + +def corrupt(bdev, block): + addr = block * bdev.ERASE_BLOCK_SIZE + for i in range(bdev.ERASE_BLOCK_SIZE): + bdev.data[addr + i] = i & 0xff + +def create_vfs(bdev, vfs_class): + bdev.ret = 0 + vfs_class.mkfs(bdev) + vfs = vfs_class(bdev) + with vfs.open('f', 'w') as f: + for i in range(100): + f.write('test') + return vfs + +def test(bdev, vfs_class): + print('test', vfs_class) + + # statvfs + vfs = create_vfs(bdev, vfs_class) + corrupt(bdev, 0) + corrupt(bdev, 1) + try: + print(vfs.statvfs('')) + except OSError: + print('statvfs OSError') + + # error during read + vfs = create_vfs(bdev, vfs_class) + f = vfs.open('f', 'r') + bdev.ret = -5 # EIO + try: + f.read(10) + except OSError: + print('read OSError') + + # error during write + vfs = create_vfs(bdev, vfs_class) + f = vfs.open('f', 'a') + bdev.ret = -5 # EIO + try: + f.write('test') + except OSError: + print('write OSError') + + # error during close + vfs = create_vfs(bdev, vfs_class) + f = vfs.open('f', 'w') + f.write('test') + bdev.ret = -5 # EIO + try: + f.close() + except OSError: + print('close OSError') + + # error during flush + vfs = create_vfs(bdev, vfs_class) + f = vfs.open('f', 'w') + f.write('test') + bdev.ret = -5 # EIO + try: + f.flush() + except OSError: + print('flush OSError') + bdev.ret = 0 + f.close() + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsLfs1) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_corrupt.py.exp b/tests/extmod/vfs_lfs_corrupt.py.exp new file mode 100644 index 0000000000000..d6f5f54252f46 --- /dev/null +++ b/tests/extmod/vfs_lfs_corrupt.py.exp @@ -0,0 +1,12 @@ +test +statvfs OSError +read OSError +write OSError +close OSError +flush OSError +test +statvfs OSError +read OSError +write OSError +close OSError +flush OSError diff --git a/tests/extmod/vfs_lfs_error.py b/tests/extmod/vfs_lfs_error.py new file mode 100644 index 0000000000000..b97fe6ec159b4 --- /dev/null +++ b/tests/extmod/vfs_lfs_error.py @@ -0,0 +1,116 @@ +# Test for VfsLittle using a RAM device, testing error handling + +try: + import uos + uos.VfsLfs1 + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 1024 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + +def test(bdev, vfs_class): + print('test', vfs_class) + + # mkfs with too-small block device + try: + vfs_class.mkfs(RAMBlockDevice(1)) + except OSError: + print('mkfs OSError') + + # mount with invalid filesystem + try: + vfs_class(bdev) + except OSError: + print('mount OSError') + + # set up for following tests + vfs_class.mkfs(bdev) + vfs = vfs_class(bdev) + with vfs.open('testfile', 'w') as f: + f.write('test') + vfs.mkdir('testdir') + + # ilistdir + try: + vfs.ilistdir('noexist') + except OSError: + print('ilistdir OSError') + + # remove + try: + vfs.remove('noexist') + except OSError: + print('remove OSError') + + # rmdir + try: + vfs.rmdir('noexist') + except OSError: + print('rmdir OSError') + + # rename + try: + vfs.rename('noexist', 'somethingelse') + except OSError: + print('rename OSError') + + # mkdir + try: + vfs.mkdir('testdir') + except OSError: + print('mkdir OSError') + + # chdir to nonexistent + try: + vfs.chdir('noexist') + except OSError: + print('chdir OSError') + print(vfs.getcwd()) # check still at root + + # chdir to file + try: + vfs.chdir('testfile') + except OSError: + print('chdir OSError') + print(vfs.getcwd()) # check still at root + + # stat + try: + vfs.stat('noexist') + except OSError: + print('stat OSError') + + # error during seek + with vfs.open('testfile', 'r') as f: + try: + f.seek(1 << 31) + except OSError: + print('seek OSError') + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsLfs1) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_error.py.exp b/tests/extmod/vfs_lfs_error.py.exp new file mode 100644 index 0000000000000..f4327f6962ec3 --- /dev/null +++ b/tests/extmod/vfs_lfs_error.py.exp @@ -0,0 +1,28 @@ +test +mkfs OSError +mount OSError +ilistdir OSError +remove OSError +rmdir OSError +rename OSError +mkdir OSError +chdir OSError +/ +chdir OSError +/ +stat OSError +seek OSError +test +mkfs OSError +mount OSError +ilistdir OSError +remove OSError +rmdir OSError +rename OSError +mkdir OSError +chdir OSError +/ +chdir OSError +/ +stat OSError +seek OSError diff --git a/tests/extmod/vfs_lfs_file.py b/tests/extmod/vfs_lfs_file.py new file mode 100644 index 0000000000000..477a62e2ffa32 --- /dev/null +++ b/tests/extmod/vfs_lfs_file.py @@ -0,0 +1,117 @@ +# Test for VfsLittle using a RAM device, file IO + +try: + import uos + uos.VfsLfs1 + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 1024 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + +def test(bdev, vfs_class): + print('test', vfs_class) + + # mkfs + vfs_class.mkfs(bdev) + + # construction + vfs = vfs_class(bdev) + + # create text, print, write, close + f = vfs.open('test.txt', 'wt') + print(f) + f.write('littlefs') + f.close() + + # close already-closed file + f.close() + + # create binary, print, write, flush, close + f = vfs.open('test.bin', 'wb') + print(f) + f.write('littlefs') + f.flush() + f.close() + + # create for append + f = vfs.open('test.bin', 'ab') + f.write('more') + f.close() + + # create exclusive + f = vfs.open('test2.bin', 'xb') + f.close() + + # create exclusive with error + try: + vfs.open('test2.bin', 'x') + except OSError: + print('open OSError') + + # read default + with vfs.open('test.txt', '') as f: + print(f.read()) + + # read text + with vfs.open('test.txt', 'rt') as f: + print(f.read()) + + # read binary + with vfs.open('test.bin', 'rb') as f: + print(f.read()) + + # create read and write + with vfs.open('test.bin', 'r+b') as f: + print(f.read(8)) + f.write('MORE') + with vfs.open('test.bin', 'rb') as f: + print(f.read()) + + # seek and tell + f = vfs.open('test.txt', 'r') + print(f.tell()) + f.seek(3, 0) + print(f.tell()) + f.close() + + # open nonexistent + try: + vfs.open('noexist', 'r') + except OSError: + print('open OSError') + + # open multiple files at the same time + f1 = vfs.open('test.txt', '') + f2 = vfs.open('test.bin', 'b') + print(f1.read()) + print(f2.read()) + f1.close() + f2.close() + +bdev = RAMBlockDevice(30) +test(bdev, uos.VfsLfs1) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_file.py.exp b/tests/extmod/vfs_lfs_file.py.exp new file mode 100644 index 0000000000000..55531539ec7de --- /dev/null +++ b/tests/extmod/vfs_lfs_file.py.exp @@ -0,0 +1,28 @@ +test + + +open OSError +littlefs +littlefs +b'littlefsmore' +b'littlefs' +b'littlefsMORE' +0 +3 +open OSError +littlefs +b'littlefsMORE' +test + + +open OSError +littlefs +littlefs +b'littlefsmore' +b'littlefs' +b'littlefsMORE' +0 +3 +open OSError +littlefs +b'littlefsMORE' diff --git a/tests/extmod/vfs_lfs_mount.py b/tests/extmod/vfs_lfs_mount.py new file mode 100644 index 0000000000000..76263f49786d3 --- /dev/null +++ b/tests/extmod/vfs_lfs_mount.py @@ -0,0 +1,73 @@ +# Test for VfsLittle using a RAM device, with mount/umount + +try: + import uos + uos.VfsLfs1 + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 1024 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + +def test(bdev, vfs_class): + print('test', vfs_class) + + # mkfs + vfs_class.mkfs(bdev) + + # construction + vfs = vfs_class(bdev) + + # mount + uos.mount(vfs, '/lfs') + + # import + with open('/lfs/lfsmod.py', 'w') as f: + f.write('print("hello from lfs")\n') + import lfsmod + + # import package + uos.mkdir('/lfs/lfspkg') + with open('/lfs/lfspkg/__init__.py', 'w') as f: + f.write('print("package")\n') + import lfspkg + + # umount + uos.umount('/lfs') + + # clear imported modules + sys.modules.clear() + +bdev = RAMBlockDevice(30) + +# initialise path +import sys +sys.path.clear() +sys.path.append('/lfs') + +# run tests +test(bdev, uos.VfsLfs1) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_mount.py.exp b/tests/extmod/vfs_lfs_mount.py.exp new file mode 100644 index 0000000000000..90aff35016111 --- /dev/null +++ b/tests/extmod/vfs_lfs_mount.py.exp @@ -0,0 +1,6 @@ +test +hello from lfs +package +test +hello from lfs +package From 7c8fb27f38b06b5067d913e9d57f87005445601b Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 27 Oct 2019 20:15:29 +1100 Subject: [PATCH 0635/1299] tests/extmod: Add test for blockdev with standard and extended protocol. --- tests/extmod/vfs_blockdev.py | 70 ++++++++++++++++++++++++++++++++ tests/extmod/vfs_blockdev.py.exp | 8 ++++ 2 files changed, 78 insertions(+) create mode 100644 tests/extmod/vfs_blockdev.py create mode 100644 tests/extmod/vfs_blockdev.py.exp diff --git a/tests/extmod/vfs_blockdev.py b/tests/extmod/vfs_blockdev.py new file mode 100644 index 0000000000000..d82b10610f34b --- /dev/null +++ b/tests/extmod/vfs_blockdev.py @@ -0,0 +1,70 @@ +# Test for behaviour of combined standard and extended block device + +try: + import uos + uos.VfsFat + uos.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off=0): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off=None): + if off is None: + # erase, then write + off = 0 + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + +def test(bdev, vfs_class): + print('test', vfs_class) + + # mkfs + vfs_class.mkfs(bdev) + + # construction + vfs = vfs_class(bdev) + + # statvfs + print(vfs.statvfs('/')) + + # open, write close + f = vfs.open('test', 'w') + for i in range(10): + f.write('some data') + f.close() + + # ilistdir + print(list(vfs.ilistdir())) + + # read + with vfs.open('test', 'r') as f: + print(f.read()) + +try: + bdev = RAMBlockDevice(50) +except MemoryError: + print("SKIP") + raise SystemExit + +test(bdev, uos.VfsFat) +test(bdev, uos.VfsLfs2) diff --git a/tests/extmod/vfs_blockdev.py.exp b/tests/extmod/vfs_blockdev.py.exp new file mode 100644 index 0000000000000..a254133131158 --- /dev/null +++ b/tests/extmod/vfs_blockdev.py.exp @@ -0,0 +1,8 @@ +test +(512, 512, 16, 16, 16, 0, 0, 0, 0, 255) +[('test', 32768, 0, 90)] +some datasome datasome datasome datasome datasome datasome datasome datasome datasome data +test +(512, 512, 50, 48, 48, 0, 0, 0, 0, 255) +[('test', 32768, 0, 90)] +some datasome datasome datasome datasome datasome datasome datasome datasome datasome data From cfe1c5abf884027eb0a5792d5a980fee8757051a Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 12:25:30 +1100 Subject: [PATCH 0636/1299] extmod/vfs: Rename BP_IOCTL_xxx constants to MP_BLOCKDEV_IOCTL_xxx. Also rename SEC_COUNT to BLOCK_COUNT and SEC_SIZE to BLOCK_SIZE. --- extmod/vfs.h | 10 +++++----- extmod/vfs_blockdev.c | 8 ++++---- extmod/vfs_fat.c | 2 +- extmod/vfs_fat_diskio.c | 8 ++++---- extmod/vfs_lfsx.c | 8 ++++---- ports/cc3200/mods/pybflash.c | 10 +++++----- ports/cc3200/mods/pybsd.c | 10 +++++----- ports/esp32/esp32_partition.c | 10 +++++----- ports/esp32/machine_sdcard.c | 10 +++++----- ports/esp8266/modules/flashbdev.py | 4 ++-- ports/stm32/sdcard.c | 10 +++++----- ports/stm32/storage.c | 10 +++++----- ports/stm32/usbd_msc_interface.c | 24 ++++++++++++------------ tests/extmod/vfs_fat_fileio1.py | 4 ++-- tests/extmod/vfs_fat_fileio2.py | 4 ++-- tests/extmod/vfs_fat_more.py | 4 ++-- tests/extmod/vfs_fat_ramdisk.py | 4 ++-- tests/extmod/vfs_fat_ramdisklarge.py | 4 ++-- 18 files changed, 72 insertions(+), 72 deletions(-) diff --git a/extmod/vfs.h b/extmod/vfs.h index 767ba3033a1c7..15bd2a5f51e5d 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -45,11 +45,11 @@ #define MP_BLOCKDEV_FLAG_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it // constants for block protocol ioctl -#define BP_IOCTL_INIT (1) -#define BP_IOCTL_DEINIT (2) -#define BP_IOCTL_SYNC (3) -#define BP_IOCTL_SEC_COUNT (4) -#define BP_IOCTL_SEC_SIZE (5) +#define MP_BLOCKDEV_IOCTL_INIT (1) +#define MP_BLOCKDEV_IOCTL_DEINIT (2) +#define MP_BLOCKDEV_IOCTL_SYNC (3) +#define MP_BLOCKDEV_IOCTL_BLOCK_COUNT (4) +#define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5) // At the moment the VFS protocol just has import_stat, but could be extended to other methods typedef struct _mp_vfs_proto_t { diff --git a/extmod/vfs_blockdev.c b/extmod/vfs_blockdev.c index 916d71ca47f70..90675aa34f06f 100644 --- a/extmod/vfs_blockdev.c +++ b/extmod/vfs_blockdev.c @@ -119,20 +119,20 @@ mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t } else { // Old protocol with sync and count switch (cmd) { - case BP_IOCTL_SYNC: + case MP_BLOCKDEV_IOCTL_SYNC: if (self->u.old.sync[0] != MP_OBJ_NULL) { mp_call_method_n_kw(0, 0, self->u.old.sync); } break; - case BP_IOCTL_SEC_COUNT: + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return mp_call_method_n_kw(0, 0, self->u.old.count); - case BP_IOCTL_SEC_SIZE: + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: // Old protocol has fixed sector size of 512 bytes break; - case BP_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_INIT: // Old protocol doesn't have init break; } diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 129b6cc6695f0..f8cb1f5a52a32 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -72,7 +72,7 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_ // Initialise underlying block device vfs->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; - vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to BP_IOCTL_SEC_SIZE + vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE mp_vfs_blockdev_init(&vfs->blockdev, args[0]); // mount the block device so the VFS methods can be used diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index 61a4d6da50e1f..76a918fa38876 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -113,10 +113,10 @@ DRESULT disk_ioctl ( // First part: call the relevant method of the underlying block device static const uint8_t op_map[8] = { - [CTRL_SYNC] = BP_IOCTL_SYNC, - [GET_SECTOR_COUNT] = BP_IOCTL_SEC_COUNT, - [GET_SECTOR_SIZE] = BP_IOCTL_SEC_SIZE, - [IOCTL_INIT] = BP_IOCTL_INIT, + [CTRL_SYNC] = MP_BLOCKDEV_IOCTL_SYNC, + [GET_SECTOR_COUNT] = MP_BLOCKDEV_IOCTL_BLOCK_COUNT, + [GET_SECTOR_SIZE] = MP_BLOCKDEV_IOCTL_BLOCK_SIZE, + [IOCTL_INIT] = MP_BLOCKDEV_IOCTL_INIT, }; uint8_t bp_op = op_map[cmd & 7]; mp_obj_t ret = mp_const_none; diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index a042f5ed1eaea..6aa82b1ef91ee 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -56,7 +56,7 @@ STATIC int MP_VFS_LFSx(dev_erase)(const struct LFSx_API(config) *c, LFSx_API(blo } STATIC int MP_VFS_LFSx(dev_sync)(const struct LFSx_API(config) *c) { - return MP_VFS_LFSx(dev_ioctl)(c, BP_IOCTL_SYNC, 0, false); + return MP_VFS_LFSx(dev_ioctl)(c, MP_BLOCKDEV_IOCTL_SYNC, 0, false); } STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx *self, mp_obj_t bdev, size_t read_size, size_t prog_size, size_t lookahead) { @@ -73,9 +73,9 @@ STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx *self, mp_obj_t bdev, size_ config->erase = MP_VFS_LFSx(dev_erase); config->sync = MP_VFS_LFSx(dev_sync); - MP_VFS_LFSx(dev_ioctl)(config, BP_IOCTL_INIT, 0, false); // initialise block device - int bs = MP_VFS_LFSx(dev_ioctl)(config, BP_IOCTL_SEC_SIZE, 0, true); // get block size - int bc = MP_VFS_LFSx(dev_ioctl)(config, BP_IOCTL_SEC_COUNT, 0, true); // get block count + MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_INIT, 0, false); // initialise block device + int bs = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_SIZE, 0, true); // get block size + int bc = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_COUNT, 0, true); // get block count self->blockdev.block_size = bs; config->read_size = read_size; diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c index 185913ce31fa7..b586195213164 100644 --- a/ports/cc3200/mods/pybflash.c +++ b/ports/cc3200/mods/pybflash.c @@ -69,11 +69,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_writeblocks_obj, pyb_flash_writeblock STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { - case BP_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(sflash_disk_init() != RES_OK); - case BP_IOCTL_DEINIT: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SYNC: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(SFLASH_SECTOR_COUNT); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(SFLASH_SECTOR_SIZE); + case MP_BLOCKDEV_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(sflash_disk_init() != RES_OK); + case MP_BLOCKDEV_IOCTL_DEINIT: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_SYNC: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(SFLASH_SECTOR_COUNT); + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(SFLASH_SECTOR_SIZE); default: return mp_const_none; } } diff --git a/ports/cc3200/mods/pybsd.c b/ports/cc3200/mods/pybsd.c index c47d4e94516b4..e5a6e2624d801 100644 --- a/ports/cc3200/mods/pybsd.c +++ b/ports/cc3200/mods/pybsd.c @@ -184,16 +184,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sd_writeblocks_obj, pyb_sd_writeblocks); STATIC mp_obj_t pyb_sd_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { - case BP_IOCTL_INIT: - case BP_IOCTL_DEINIT: - case BP_IOCTL_SYNC: + case MP_BLOCKDEV_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: // nothing to do return MP_OBJ_NEW_SMALL_INT(0); // success - case BP_IOCTL_SEC_COUNT: + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(sd_disk_info.ulNofBlock * (sd_disk_info.ulBlockSize / 512)); - case BP_IOCTL_SEC_SIZE: + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(SD_SECTOR_SIZE); default: // unknown command diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index 49bb0632e3986..52b3859ff085e 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -173,11 +173,11 @@ STATIC mp_obj_t esp32_partition_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_ esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { - case BP_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SYNC: return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(self->part->size / BLOCK_SIZE_BYTES); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(BLOCK_SIZE_BYTES); + case MP_BLOCKDEV_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_DEINIT: return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_SYNC: return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(self->part->size / BLOCK_SIZE_BYTES); + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(BLOCK_SIZE_BYTES); default: return mp_const_none; } } diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 1400c56f35237..8639e4104c758 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -337,26 +337,26 @@ STATIC mp_obj_t machine_sdcard_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { - case BP_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_INIT: err = sdcard_ensure_card_init(self, false); return MP_OBJ_NEW_SMALL_INT((err == ESP_OK) ? 0 : -1); - case BP_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_DEINIT: // Ensure that future attempts to look at info re-read the card self->flags &= ~SDCARD_CARD_FLAGS_CARD_INIT_DONE; return MP_OBJ_NEW_SMALL_INT(0); // success - case BP_IOCTL_SYNC: + case MP_BLOCKDEV_IOCTL_SYNC: // nothing to do return MP_OBJ_NEW_SMALL_INT(0); // success - case BP_IOCTL_SEC_COUNT: + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: err = sdcard_ensure_card_init(self, false); if (err != ESP_OK) return MP_OBJ_NEW_SMALL_INT(-1); return MP_OBJ_NEW_SMALL_INT(self->card.csd.capacity); - case BP_IOCTL_SEC_SIZE: + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: err = sdcard_ensure_card_init(self, false); if (err != ESP_OK) return MP_OBJ_NEW_SMALL_INT(-1); diff --git a/ports/esp8266/modules/flashbdev.py b/ports/esp8266/modules/flashbdev.py index 40ba655c64d10..80ddcfbf917bc 100644 --- a/ports/esp8266/modules/flashbdev.py +++ b/ports/esp8266/modules/flashbdev.py @@ -22,9 +22,9 @@ def writeblocks(self, n, buf): def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return self.blocks - if op == 5: # BP_IOCTL_SEC_SIZE + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE size = esp.flash_size() diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index da9c1c681a887..c6832ceb8017c 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -812,24 +812,24 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sdcard_writeblocks_obj, pyb_sdcard_writeblo STATIC mp_obj_t pyb_sdcard_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { - case BP_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_INIT: if (!sdcard_power_on()) { return MP_OBJ_NEW_SMALL_INT(-1); // error } return MP_OBJ_NEW_SMALL_INT(0); // success - case BP_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_DEINIT: sdcard_power_off(); return MP_OBJ_NEW_SMALL_INT(0); // success - case BP_IOCTL_SYNC: + case MP_BLOCKDEV_IOCTL_SYNC: // nothing to do return MP_OBJ_NEW_SMALL_INT(0); // success - case BP_IOCTL_SEC_COUNT: + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(sdcard_get_capacity_in_bytes() / SDCARD_BLOCK_SIZE); - case BP_IOCTL_SEC_SIZE: + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(SDCARD_BLOCK_SIZE); default: // unknown command diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index 7685f6f175b8c..d9d5464855894 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -263,11 +263,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_writeblocks_obj, pyb_flash_writeblock STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { - case BP_IOCTL_INIT: storage_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(storage_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(storage_get_block_size()); + case MP_BLOCKDEV_IOCTL_INIT: storage_init(); return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_DEINIT: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly + case MP_BLOCKDEV_IOCTL_SYNC: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(storage_get_block_count()); + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(storage_get_block_size()); default: return mp_const_none; } } diff --git a/ports/stm32/usbd_msc_interface.c b/ports/stm32/usbd_msc_interface.c index 7f563004b896e..2f5e7aa7d3fd6 100644 --- a/ports/stm32/usbd_msc_interface.c +++ b/ports/stm32/usbd_msc_interface.c @@ -121,17 +121,17 @@ STATIC int lu_ioctl(uint8_t lun, int op, uint32_t *data) { if (lu == &pyb_flash_type) { switch (op) { - case BP_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_INIT: storage_init(); *data = 0; return 0; - case BP_IOCTL_SYNC: + case MP_BLOCKDEV_IOCTL_SYNC: storage_flush(); return 0; - case BP_IOCTL_SEC_SIZE: + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: *data = storage_get_block_size(); return 0; - case BP_IOCTL_SEC_COUNT: + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: *data = storage_get_block_count(); return 0; default: @@ -144,18 +144,18 @@ STATIC int lu_ioctl(uint8_t lun, int op, uint32_t *data) { #endif ) { switch (op) { - case BP_IOCTL_INIT: + case MP_BLOCKDEV_IOCTL_INIT: if (!sdcard_power_on()) { return -1; } *data = 0; return 0; - case BP_IOCTL_SYNC: + case MP_BLOCKDEV_IOCTL_SYNC: return 0; - case BP_IOCTL_SEC_SIZE: + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: *data = SDCARD_BLOCK_SIZE; return 0; - case BP_IOCTL_SEC_COUNT: + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: *data = sdcard_get_capacity_in_bytes() / (uint64_t)SDCARD_BLOCK_SIZE; return 0; default: @@ -174,7 +174,7 @@ STATIC int8_t usbd_msc_Init(uint8_t lun_in) { } for (int lun = 0; lun < usbd_msc_lu_num; ++lun) { uint32_t data = 0; - int res = lu_ioctl(lun, BP_IOCTL_INIT, &data); + int res = lu_ioctl(lun, MP_BLOCKDEV_IOCTL_INIT, &data); if (res != 0) { lu_flag_clr(lun, FLAGS_STARTED); } else { @@ -234,12 +234,12 @@ STATIC int usbd_msc_Inquiry(uint8_t lun, const uint8_t *params, uint8_t *data_ou // Get storage capacity of a logical unit STATIC int8_t usbd_msc_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { uint32_t block_size_u32 = 0; - int res = lu_ioctl(lun, BP_IOCTL_SEC_SIZE, &block_size_u32); + int res = lu_ioctl(lun, MP_BLOCKDEV_IOCTL_BLOCK_SIZE, &block_size_u32); if (res != 0) { return -1; } *block_size = block_size_u32; - return lu_ioctl(lun, BP_IOCTL_SEC_COUNT, block_num); + return lu_ioctl(lun, MP_BLOCKDEV_IOCTL_BLOCK_COUNT, block_num); } // Check if a logical unit is ready @@ -275,7 +275,7 @@ STATIC int8_t usbd_msc_StartStopUnit(uint8_t lun, uint8_t started) { STATIC int8_t usbd_msc_PreventAllowMediumRemoval(uint8_t lun, uint8_t param) { uint32_t dummy; // Sync the logical unit so the device can be unplugged/turned off - return lu_ioctl(lun, BP_IOCTL_SYNC, &dummy); + return lu_ioctl(lun, MP_BLOCKDEV_IOCTL_SYNC, &dummy); } // Read data from a logical unit diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py index 51cd765222cd0..d0a5e4b73ca3e 100644 --- a/tests/extmod/vfs_fat_fileio1.py +++ b/tests/extmod/vfs_fat_fileio1.py @@ -31,9 +31,9 @@ def writeblocks(self, n, buf): def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE - if op == 5: # BP_IOCTL_SEC_SIZE + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE diff --git a/tests/extmod/vfs_fat_fileio2.py b/tests/extmod/vfs_fat_fileio2.py index 9b9a11e435b7f..6721f9b9349d0 100644 --- a/tests/extmod/vfs_fat_fileio2.py +++ b/tests/extmod/vfs_fat_fileio2.py @@ -31,9 +31,9 @@ def writeblocks(self, n, buf): def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE - if op == 5: # BP_IOCTL_SEC_SIZE + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE diff --git a/tests/extmod/vfs_fat_more.py b/tests/extmod/vfs_fat_more.py index 488697fa856f1..9505fd3282ed3 100644 --- a/tests/extmod/vfs_fat_more.py +++ b/tests/extmod/vfs_fat_more.py @@ -30,9 +30,9 @@ def writeblocks(self, n, buf): def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE - if op == 5: # BP_IOCTL_SEC_SIZE + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index f6e5c64df0533..11b2df7f42ecd 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -31,9 +31,9 @@ def writeblocks(self, n, buf): def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return len(self.data) // self.SEC_SIZE - if op == 5: # BP_IOCTL_SEC_SIZE + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE diff --git a/tests/extmod/vfs_fat_ramdisklarge.py b/tests/extmod/vfs_fat_ramdisklarge.py index 6f95910315eab..4ac52b257f208 100644 --- a/tests/extmod/vfs_fat_ramdisklarge.py +++ b/tests/extmod/vfs_fat_ramdisklarge.py @@ -39,9 +39,9 @@ def writeblocks(self, n, buf): def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) - if op == 4: # BP_IOCTL_SEC_COUNT + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT return self.blocks - if op == 5: # BP_IOCTL_SEC_SIZE + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE From 4cf054a130e90bec19399ef2b8181d434dd22d8e Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 12:29:56 +1100 Subject: [PATCH 0637/1299] extmod/vfs: Add MP_BLOCKDEV_IOCTL_BLOCK_ERASE constant. --- extmod/vfs.h | 1 + extmod/vfs_lfsx.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extmod/vfs.h b/extmod/vfs.h index 15bd2a5f51e5d..004b002f55bba 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -50,6 +50,7 @@ #define MP_BLOCKDEV_IOCTL_SYNC (3) #define MP_BLOCKDEV_IOCTL_BLOCK_COUNT (4) #define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5) +#define MP_BLOCKDEV_IOCTL_BLOCK_ERASE (6) // At the moment the VFS protocol just has import_stat, but could be extended to other methods typedef struct _mp_vfs_proto_t { diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index 6aa82b1ef91ee..e5826803b2433 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -52,7 +52,7 @@ STATIC int MP_VFS_LFSx(dev_prog)(const struct LFSx_API(config) *c, LFSx_API(bloc } STATIC int MP_VFS_LFSx(dev_erase)(const struct LFSx_API(config) *c, LFSx_API(block_t) block) { - return MP_VFS_LFSx(dev_ioctl)(c, 6, block, true); // erase + return MP_VFS_LFSx(dev_ioctl)(c, MP_BLOCKDEV_IOCTL_BLOCK_ERASE, block, true); } STATIC int MP_VFS_LFSx(dev_sync)(const struct LFSx_API(config) *c) { From 7a24b7f0911c8632651616601f02e746eea1c73c Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 12:32:56 +1100 Subject: [PATCH 0638/1299] docs/library: Add documentation for extended block device protocol. --- docs/library/uos.rst | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/docs/library/uos.rst b/docs/library/uos.rst index 58ac83b2b123b..d8d8b7a972eeb 100644 --- a/docs/library/uos.rst +++ b/docs/library/uos.rst @@ -187,25 +187,51 @@ implementation of this class will usually allow access to the memory-like functionality a piece of hardware (like flash memory). A block device can be used by a particular filesystem driver to store the data for its filesystem. +There are two compatible signatures for the ``readblocks`` and ``writeblocks`` +methods (see below), in order to support a variety of use cases. A given block +device may implement one form or the other, or both at the same time. + .. class:: AbstractBlockDev(...) Construct a block device object. The parameters to the constructor are dependent on the specific block device. .. method:: readblocks(block_num, buf) + .. method:: readblocks(block_num, buf, offset) + The first form reads aligned, multiples of blocks. Starting at the block given by the index *block_num*, read blocks from the device into *buf* (an array of bytes). The number of blocks to read is given by the length of *buf*, which will be a multiple of the block size. + The second form allows reading at arbitrary locations within a block, + and arbitrary lengths. + Starting at block index *block_num*, and byte offset within that block + of *offset*, read bytes from the device into *buf* (an array of bytes). + The number of bytes to read is given by the length of *buf*. + .. method:: writeblocks(block_num, buf) + .. method:: writeblocks(block_num, buf, offset) + The first form writes aligned, multiples of blocks, and requires that the + blocks that are written to be first erased (if necessary) by this method. Starting at the block given by the index *block_num*, write blocks from *buf* (an array of bytes) to the device. The number of blocks to write is given by the length of *buf*, which will be a multiple of the block size. + The second form allows writing at arbitrary locations within a block, + and arbitrary lengths. Only the bytes being written should be changed, + and the caller of this method must ensure that the relevant blocks are + erased via a prior ``ioctl`` call. + Starting at block index *block_num*, and byte offset within that block + of *offset*, write bytes from *buf* (an array of bytes) to the device. + The number of bytes to write is given by the length of *buf*. + + Note that implementations must never implicitly erase blocks if the offset + argument is specified, even if it is zero. + .. method:: ioctl(op, arg) Control the block device and query its parameters. The operation to @@ -219,6 +245,7 @@ used by a particular filesystem driver to store the data for its filesystem. - 5 -- get the number of bytes in a block, should return an integer, or ``None`` in which case the default value of 512 is used (*arg* is unused) + - 6 -- erase a block, *arg* is the block number to erase By way of example, the following class will implement a block device that stores its data in RAM using a ``bytearray``:: @@ -250,3 +277,34 @@ It can be used as follows:: uos.VfsFat.mkfs(bdev) vfs = uos.VfsFat(bdev) uos.mount(vfs, '/ramdisk') + +An example of a block device that supports both signatures and behaviours of +the :meth:`readblocks` and :meth:`writeblocks` methods is:: + + class RAMBlockDev: + def __init__(self, block_size, num_blocks): + self.block_size = block_size + self.data = bytearray(block_size * num_blocks) + + def readblocks(self, block, buf, offset=0): + addr = block_num * self.block_size + offset + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block_num, buf, offset=None): + if offset is None: + # do erase, then write + for i in range(len(buf) // self.block_size): + self.ioctl(6, block_num + i) + offset = 0 + addr = block_num * self.block_size + offset + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.block_size + if op == 5: # block size + return self.block_size + if op == 6: # block erase + return 0 From 4847460232764a116b731da077074818e316fb55 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 15:41:36 +1100 Subject: [PATCH 0639/1299] unix/mphalport.h: Define mp_hal_stdio_poll to dummy because it's unused. And requires uintptr_t to declare the default version in py/mphal.h. --- ports/unix/mphalport.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/unix/mphalport.h b/ports/unix/mphalport.h index ff7a51567c909..e3e045aed1921 100644 --- a/ports/unix/mphalport.h +++ b/ports/unix/mphalport.h @@ -31,6 +31,7 @@ void mp_hal_set_interrupt_char(char c); +#define mp_hal_stdio_poll unused // this is not implemented, nor needed void mp_hal_stdio_mode_raw(void); void mp_hal_stdio_mode_orig(void); From 709136e844f93eb7b9ea8c14e9daa5da8e8293d3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 19:18:06 +1100 Subject: [PATCH 0640/1299] tests/basics: Use str.format instead of % for formatting messages. Only use % formatting when testing % itself, because only str.format is guaranteed to be available on any port. --- tests/basics/async_await2.py | 2 +- tests/basics/class_inplace_op.py | 4 ++-- tests/basics/class_notimpl.py | 2 +- tests/basics/class_reverse_op.py | 2 +- tests/basics/string_repr.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/basics/async_await2.py b/tests/basics/async_await2.py index 129d3751a59b2..1e3164df93372 100644 --- a/tests/basics/async_await2.py +++ b/tests/basics/async_await2.py @@ -11,7 +11,7 @@ @coroutine def wait(value): print('wait value:', value) - msg = yield 'message from wait(%u)' % value + msg = yield 'message from wait({})'.format(value) print('wait got back:', msg) return 10 diff --git a/tests/basics/class_inplace_op.py b/tests/basics/class_inplace_op.py index 62aad8c7cfc61..8885bdaa850f8 100644 --- a/tests/basics/class_inplace_op.py +++ b/tests/basics/class_inplace_op.py @@ -10,7 +10,7 @@ def __add__(self, o): return A(self.v + o.v) def __repr__(self): - return "A(%s)" % self.v + return "A({})".format(self.v) a = A(5) b = a @@ -37,7 +37,7 @@ def __iadd__(self, o): return self def __repr__(self): - return "L(%s)" % self.v + return "L({})".format(self.v) c = L([1, 2]) d = c diff --git a/tests/basics/class_notimpl.py b/tests/basics/class_notimpl.py index 7fd8166f90840..308075f92f3ef 100644 --- a/tests/basics/class_notimpl.py +++ b/tests/basics/class_notimpl.py @@ -11,7 +11,7 @@ def __init__(self, value): self.value = value def __str__(self): - return "C(%s)" % self.value + return "C({})".format(self.value) def __add__(self, rhs): print(self, '+', rhs) diff --git a/tests/basics/class_reverse_op.py b/tests/basics/class_reverse_op.py index d41c55c9d764e..b0dae5f8a336c 100644 --- a/tests/basics/class_reverse_op.py +++ b/tests/basics/class_reverse_op.py @@ -12,7 +12,7 @@ def __radd__(self, o): return A(self.v + o) def __repr__(self): - return "A(%s)" % self.v + return "A({})".format(self.v) print(A(3) + 1) print(2 + A(5)) diff --git a/tests/basics/string_repr.py b/tests/basics/string_repr.py index 2a3ef2527c592..b4842e1475f9b 100644 --- a/tests/basics/string_repr.py +++ b/tests/basics/string_repr.py @@ -1,4 +1,4 @@ # anything above 0xa0 is printed as Unicode by CPython # the abobe is CPython implementation detail, stick to ASCII for c in range(0x80): - print("0x%02x: %s" % (c, repr(chr(c)))) + print("0x{:02x}: {}".format(c, repr(chr(c)))) From 7a49fc387c2ecbc374967f1ebc221770c2ca4b7a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 19:26:30 +1100 Subject: [PATCH 0641/1299] tests/basics/builtin_dir.py: Look for "version" in dir(sys). Because "version" will always be there, but "exit" may not. --- tests/basics/builtin_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basics/builtin_dir.py b/tests/basics/builtin_dir.py index c15a76f4c6d30..1eecbd044b7b0 100644 --- a/tests/basics/builtin_dir.py +++ b/tests/basics/builtin_dir.py @@ -5,7 +5,7 @@ # dir of module import sys -print('exit' in dir(sys)) +print('version' in dir(sys)) # dir of type print('append' in dir(list)) From 6e9ba1cf4b0cd8e2986e9abe9a8a66c43a43c63a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 18 Oct 2019 19:48:15 +1100 Subject: [PATCH 0642/1299] tests: Add feature check for bytearray and skip corresponding tests. --- tests/feature_check/bytearray.py | 5 +++++ tests/feature_check/bytearray.py.exp | 0 tests/run-tests | 8 ++++++++ 3 files changed, 13 insertions(+) create mode 100644 tests/feature_check/bytearray.py create mode 100644 tests/feature_check/bytearray.py.exp diff --git a/tests/feature_check/bytearray.py b/tests/feature_check/bytearray.py new file mode 100644 index 0000000000000..601ef4597c442 --- /dev/null +++ b/tests/feature_check/bytearray.py @@ -0,0 +1,5 @@ +try: + bytearray + print("bytearray") +except NameError: + print("no") diff --git a/tests/feature_check/bytearray.py.exp b/tests/feature_check/bytearray.py.exp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/run-tests b/tests/run-tests index b22d067192911..9e98125797297 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -221,6 +221,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_tests = set() skip_native = False skip_int_big = False + skip_bytearray = False skip_set_type = False skip_async = False skip_const = False @@ -244,6 +245,11 @@ def run_tests(pyb, tests, args, base_path="."): if output != b'1000000000000000000000000000000000000000000000\n': skip_int_big = True + # Check if bytearray is supported, and skip such tests if it's not + output = run_feature_check(pyb, args, base_path, 'bytearray.py') + if output != b'bytearray\n': + skip_bytearray = True + # Check if set type (and set literals) is supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'set_check.py') if output == b'CRASH': @@ -397,6 +403,7 @@ def run_tests(pyb, tests, args, base_path="."): is_native = test_name.startswith("native_") or test_name.startswith("viper_") is_endian = test_name.endswith("_endian") is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig") + is_bytearray = test_name.startswith("bytearray") or test_name.endswith("_bytearray") is_set_type = test_name.startswith("set_") or test_name.startswith("frozenset") is_async = test_name.startswith("async_") is_const = test_name.startswith("const") @@ -405,6 +412,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_it |= skip_native and is_native skip_it |= skip_endian and is_endian skip_it |= skip_int_big and is_int_big + skip_it |= skip_bytearray and is_bytearray skip_it |= skip_set_type and is_set_type skip_it |= skip_async and is_async skip_it |= skip_const and is_const From aeea204e9802d6a175d94bdb03de428b5f1c74d1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 21:24:51 +1100 Subject: [PATCH 0643/1299] tests/basics: Split out specific bytearray tests to separate files. So they can be automatically skipped if bytearray is not enabled. --- tests/basics/bytes_add.py | 2 -- tests/basics/bytes_add_bytearray.py | 5 +++++ tests/basics/bytes_compare2.py | 4 ---- tests/basics/bytes_compare_bytearray.py | 4 ++++ tests/basics/bytes_construct.py | 3 +-- tests/basics/bytes_construct_bytearray.py | 3 +++ tests/basics/op_error.py | 14 -------------- tests/basics/op_error_bytearray.py | 19 +++++++++++++++++++ 8 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 tests/basics/bytes_add_bytearray.py create mode 100644 tests/basics/bytes_compare_bytearray.py create mode 100644 tests/basics/bytes_construct_bytearray.py create mode 100644 tests/basics/op_error_bytearray.py diff --git a/tests/basics/bytes_add.py b/tests/basics/bytes_add.py index ebccf0662dbb2..ab027a26dffdf 100644 --- a/tests/basics/bytes_add.py +++ b/tests/basics/bytes_add.py @@ -1,8 +1,6 @@ # test bytes + other print(b"123" + b"456") -print(b"123" + bytearray(2)) print(b"123" + b"") # RHS is empty, can be optimised print(b"" + b"123") # LHS is empty, can be optimised -print(b"" + bytearray(1)) # LHS is empty but can't be optimised diff --git a/tests/basics/bytes_add_bytearray.py b/tests/basics/bytes_add_bytearray.py new file mode 100644 index 0000000000000..4998800b512f5 --- /dev/null +++ b/tests/basics/bytes_add_bytearray.py @@ -0,0 +1,5 @@ +# test bytes + bytearray + +print(b"123" + bytearray(2)) + +print(b"" + bytearray(1)) # LHS is empty but can't be optimised diff --git a/tests/basics/bytes_compare2.py b/tests/basics/bytes_compare2.py index 4d5de21d2110f..8559685378d6d 100644 --- a/tests/basics/bytes_compare2.py +++ b/tests/basics/bytes_compare2.py @@ -1,5 +1 @@ print(b"1" == 1) -print(b"123" == bytearray(b"123")) -print(b'123' < bytearray(b"124")) -print(b'123' > bytearray(b"122")) -print(bytearray(b"23") in b"1234") diff --git a/tests/basics/bytes_compare_bytearray.py b/tests/basics/bytes_compare_bytearray.py new file mode 100644 index 0000000000000..6a8d8b8a51466 --- /dev/null +++ b/tests/basics/bytes_compare_bytearray.py @@ -0,0 +1,4 @@ +print(b"123" == bytearray(b"123")) +print(b'123' < bytearray(b"124")) +print(b'123' > bytearray(b"122")) +print(bytearray(b"23") in b"1234") diff --git a/tests/basics/bytes_construct.py b/tests/basics/bytes_construct.py index 0d638c08f213a..6f83f1cb20806 100644 --- a/tests/basics/bytes_construct.py +++ b/tests/basics/bytes_construct.py @@ -1,9 +1,8 @@ # test construction of bytes from different objects -# tuple, list, bytearray +# tuple, list print(bytes((1, 2))) print(bytes([1, 2])) -print(bytes(bytearray(4))) # constructor value out of range try: diff --git a/tests/basics/bytes_construct_bytearray.py b/tests/basics/bytes_construct_bytearray.py new file mode 100644 index 0000000000000..75f08acd3b772 --- /dev/null +++ b/tests/basics/bytes_construct_bytearray.py @@ -0,0 +1,3 @@ +# test construction of bytes from bytearray + +print(bytes(bytearray(4))) diff --git a/tests/basics/op_error.py b/tests/basics/op_error.py index 7b4f896e1410e..63c35db3f5f94 100644 --- a/tests/basics/op_error.py +++ b/tests/basics/op_error.py @@ -13,10 +13,6 @@ ~[] except TypeError: print('TypeError') -try: - ~bytearray() -except TypeError: - print('TypeError') # unsupported binary operators try: @@ -31,16 +27,6 @@ 1 in 1 except TypeError: print('TypeError') -try: - bytearray() // 2 -except TypeError: - print('TypeError') - -# object with buffer protocol needed on rhs -try: - bytearray(1) + 1 -except TypeError: - print('TypeError') # unsupported subscription try: diff --git a/tests/basics/op_error_bytearray.py b/tests/basics/op_error_bytearray.py new file mode 100644 index 0000000000000..9ab69371d22de --- /dev/null +++ b/tests/basics/op_error_bytearray.py @@ -0,0 +1,19 @@ +# test errors from bad operations (unary, binary, etc) + +# unsupported unary operators +try: + ~bytearray() +except TypeError: + print('TypeError') + +# unsupported binary operators +try: + bytearray() // 2 +except TypeError: + print('TypeError') + +# object with buffer protocol needed on rhs +try: + bytearray(1) + 1 +except TypeError: + print('TypeError') From 9162a87d4d21ce7f682e5d4ae7703fa1b13f45e9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 21:25:38 +1100 Subject: [PATCH 0644/1299] tests/basics: Use bytes not bytearray when checking user buffer proto. Using bytes will test the same path for the buffer protocol in py/objtype.c. --- tests/basics/class_misc.py | 2 +- tests/basics/subclass_native_buffer.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/basics/class_misc.py b/tests/basics/class_misc.py index 82b9b3479e692..34b1a3bc646bb 100644 --- a/tests/basics/class_misc.py +++ b/tests/basics/class_misc.py @@ -4,6 +4,6 @@ class C: c = C() try: - d = bytearray(c) + d = bytes(c) except TypeError: print('TypeError') diff --git a/tests/basics/subclass_native_buffer.py b/tests/basics/subclass_native_buffer.py index 43c38196570dd..00717a70e7d17 100644 --- a/tests/basics/subclass_native_buffer.py +++ b/tests/basics/subclass_native_buffer.py @@ -12,5 +12,5 @@ class my_bytes(bytes): print(b1 + b3) print(b3 + b1) -# bytearray construction will use the buffer protocol -print(bytearray(b1)) +# bytes construction will use the buffer protocol +print(bytes(b1)) From ecb77e40e079c6caef1391f48ff1ba7fab8fa68d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 21:44:22 +1100 Subject: [PATCH 0645/1299] tests: Add feature check for slice and skip corresponding tests. --- tests/feature_check/slice.py | 5 +++++ tests/feature_check/slice.py.exp | 0 tests/run-tests | 8 ++++++++ 3 files changed, 13 insertions(+) create mode 100644 tests/feature_check/slice.py create mode 100644 tests/feature_check/slice.py.exp diff --git a/tests/feature_check/slice.py b/tests/feature_check/slice.py new file mode 100644 index 0000000000000..cdd42701af227 --- /dev/null +++ b/tests/feature_check/slice.py @@ -0,0 +1,5 @@ +try: + slice + print("slice") +except NameError: + print("no") diff --git a/tests/feature_check/slice.py.exp b/tests/feature_check/slice.py.exp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/run-tests b/tests/run-tests index 9e98125797297..0fb72f3f68122 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -223,6 +223,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_int_big = False skip_bytearray = False skip_set_type = False + skip_slice = False skip_async = False skip_const = False skip_revops = False @@ -255,6 +256,11 @@ def run_tests(pyb, tests, args, base_path="."): if output == b'CRASH': skip_set_type = True + # Check if slice is supported, and skip such tests if it's not + output = run_feature_check(pyb, args, base_path, 'slice.py') + if output != b'slice\n': + skip_slice = True + # Check if async/await keywords are supported, and skip such tests if it's not output = run_feature_check(pyb, args, base_path, 'async_check.py') if output == b'CRASH': @@ -405,6 +411,7 @@ def run_tests(pyb, tests, args, base_path="."): is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig") is_bytearray = test_name.startswith("bytearray") or test_name.endswith("_bytearray") is_set_type = test_name.startswith("set_") or test_name.startswith("frozenset") + is_slice = test_name.find("slice") != -1 is_async = test_name.startswith("async_") is_const = test_name.startswith("const") @@ -414,6 +421,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_it |= skip_int_big and is_int_big skip_it |= skip_bytearray and is_bytearray skip_it |= skip_set_type and is_set_type + skip_it |= skip_slice and is_slice skip_it |= skip_async and is_async skip_it |= skip_const and is_const skip_it |= skip_revops and test_name.startswith("class_reverse_op") From b5186c9271d85c1105309ad4bf8c7d68b0d8efa7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 21:44:48 +1100 Subject: [PATCH 0646/1299] tests/basics: Split out specific slice tests to separate files. So they can be automatically skipped if slice is not enabled. --- tests/basics/list1.py | 4 ---- tests/basics/list_slice.py | 5 +++++ tests/basics/tuple1.py | 4 ---- tests/basics/tuple_slice.py | 7 +++++++ 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 tests/basics/tuple_slice.py diff --git a/tests/basics/list1.py b/tests/basics/list1.py index fa426c0e58fdd..0697c9e3a78e7 100644 --- a/tests/basics/list1.py +++ b/tests/basics/list1.py @@ -19,10 +19,6 @@ x += [2, 1] print(x) -print(x[1:]) -print(x[:-1]) -print(x[2:3]) - # unsupported type on RHS of add try: [] + None diff --git a/tests/basics/list_slice.py b/tests/basics/list_slice.py index fc08e580a17e5..6b2d2ad059b09 100644 --- a/tests/basics/list_slice.py +++ b/tests/basics/list_slice.py @@ -1,6 +1,11 @@ # test list slices, getting values x = list(range(10)) + +print(x[1:]) +print(x[:-1]) +print(x[2:3]) + a = 2 b = 4 c = 3 diff --git a/tests/basics/tuple1.py b/tests/basics/tuple1.py index a7956c107220a..72bb3f01bff4a 100644 --- a/tests/basics/tuple1.py +++ b/tests/basics/tuple1.py @@ -11,10 +11,6 @@ except AttributeError: print("AttributeError") -print(x[1:]) -print(x[:-1]) -print(x[2:3]) - print(x + (10, 100, 10000)) # inplace add operator diff --git a/tests/basics/tuple_slice.py b/tests/basics/tuple_slice.py new file mode 100644 index 0000000000000..1b11957c7a041 --- /dev/null +++ b/tests/basics/tuple_slice.py @@ -0,0 +1,7 @@ +# tuple slicing + +x = (1, 2, 3 * 4) + +print(x[1:]) +print(x[:-1]) +print(x[2:3]) From 52299ed3f011b50feb58c226764e08a995fad305 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 22:01:17 +1100 Subject: [PATCH 0647/1299] tests/run-tests: Add misc list of tests that use slice, to skip them. --- tests/run-tests | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/run-tests b/tests/run-tests index 0fb72f3f68122..5a2086c5a8da4 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -288,6 +288,22 @@ def run_tests(pyb, tests, args, base_path="."): cpy_byteorder = subprocess.check_output([CPYTHON3, base_path + '/feature_check/byteorder.py']) skip_endian = (upy_byteorder != cpy_byteorder) + # These tests don't test slice explicitly but rather use it to perform the test + misc_slice_tests = ( + 'builtin_range', + 'class_super', + 'containment', + 'errno1', + 'fun_str', + 'generator1', + 'globals_del', + 'memoryview1', + 'memoryview_gc', + 'object1', + 'python34', + 'struct_endian', + ) + # Some tests shouldn't be run under Travis CI if os.getenv('TRAVIS') == 'true': skip_tests.add('basics/memoryerror.py') @@ -411,7 +427,7 @@ def run_tests(pyb, tests, args, base_path="."): is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig") is_bytearray = test_name.startswith("bytearray") or test_name.endswith("_bytearray") is_set_type = test_name.startswith("set_") or test_name.startswith("frozenset") - is_slice = test_name.find("slice") != -1 + is_slice = test_name.find("slice") != -1 or test_name in misc_slice_tests is_async = test_name.startswith("async_") is_const = test_name.startswith("const") From eebffb2b5b46dae65eeef8290146112348415221 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 22:01:47 +1100 Subject: [PATCH 0648/1299] tests/basics: Automatically skip tests that use str/bytes modulo-format. --- tests/basics/bytes_format_modulo.py | 7 +++++++ tests/basics/string_format_modulo.py | 6 ++++++ tests/basics/string_format_modulo_int.py | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/tests/basics/bytes_format_modulo.py b/tests/basics/bytes_format_modulo.py index 70246e72dcf6c..b928f593e04ef 100644 --- a/tests/basics/bytes_format_modulo.py +++ b/tests/basics/bytes_format_modulo.py @@ -1,4 +1,11 @@ # This test requires CPython3.5 + +try: + b'' % () +except TypeError: + print("SKIP") + raise SystemExit + print(b"%%" % ()) print(b"=%d=" % 1) print(b"=%d=%d=" % (1, 2)) diff --git a/tests/basics/string_format_modulo.py b/tests/basics/string_format_modulo.py index 77bbcfbe36dd7..021b5f08d2849 100644 --- a/tests/basics/string_format_modulo.py +++ b/tests/basics/string_format_modulo.py @@ -1,3 +1,9 @@ +try: + '' % () +except TypeError: + print("SKIP") + raise SystemExit + print("%%" % ()) print("=%s=" % 1) print("=%s=%s=" % (1, 2)) diff --git a/tests/basics/string_format_modulo_int.py b/tests/basics/string_format_modulo_int.py index d1f29db2209a2..d057522bfc9ae 100644 --- a/tests/basics/string_format_modulo_int.py +++ b/tests/basics/string_format_modulo_int.py @@ -1,5 +1,11 @@ # test string modulo formatting with int values +try: + '' % () +except TypeError: + print("SKIP") + raise SystemExit + # basic cases print("%d" % 10) print("%+d" % 10) From 1d511152467ad2d21f874c9bbe05f8f117424d3e Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 22:13:38 +1100 Subject: [PATCH 0649/1299] tests: Add feature check for uio module and skip corresponding tests. --- tests/feature_check/uio_module.py | 5 +++++ tests/feature_check/uio_module.py.exp | 0 tests/run-tests | 8 ++++++++ 3 files changed, 13 insertions(+) create mode 100644 tests/feature_check/uio_module.py create mode 100644 tests/feature_check/uio_module.py.exp diff --git a/tests/feature_check/uio_module.py b/tests/feature_check/uio_module.py new file mode 100644 index 0000000000000..1031cba90914c --- /dev/null +++ b/tests/feature_check/uio_module.py @@ -0,0 +1,5 @@ +try: + import uio + print("uio") +except ImportError: + print("no") diff --git a/tests/feature_check/uio_module.py.exp b/tests/feature_check/uio_module.py.exp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/run-tests b/tests/run-tests index 5a2086c5a8da4..77667c271153f 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -227,6 +227,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_async = False skip_const = False skip_revops = False + skip_io_module = False skip_endian = False has_complex = True has_coverage = False @@ -276,6 +277,11 @@ def run_tests(pyb, tests, args, base_path="."): if output == b'TypeError\n': skip_revops = True + # Check if uio module exists, and skip such tests if it doesn't + output = run_feature_check(pyb, args, base_path, 'uio_module.py') + if output != b'uio\n': + skip_io_module = True + # Check if emacs repl is supported, and skip such tests if it's not t = run_feature_check(pyb, args, base_path, 'repl_emacs_check.py') if not 'True' in str(t, 'ascii'): @@ -430,6 +436,7 @@ def run_tests(pyb, tests, args, base_path="."): is_slice = test_name.find("slice") != -1 or test_name in misc_slice_tests is_async = test_name.startswith("async_") is_const = test_name.startswith("const") + is_io_module = test_name.startswith("io_") skip_it = test_file in skip_tests skip_it |= skip_native and is_native @@ -441,6 +448,7 @@ def run_tests(pyb, tests, args, base_path="."): skip_it |= skip_async and is_async skip_it |= skip_const and is_const skip_it |= skip_revops and test_name.startswith("class_reverse_op") + skip_it |= skip_io_module and is_io_module if args.list_tests: if not skip_it: From 943dd33b5fd36c54990ccebbd6fc30189d5373ac Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 22:16:19 +1100 Subject: [PATCH 0650/1299] tests/basics: Split sys.exit test to separate file so it can be skipped. --- tests/basics/sys1.py | 15 --------------- tests/basics/sys_exit.py | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 15 deletions(-) create mode 100644 tests/basics/sys_exit.py diff --git a/tests/basics/sys1.py b/tests/basics/sys1.py index 30e36f81a8d9a..ab913802469b7 100644 --- a/tests/basics/sys1.py +++ b/tests/basics/sys1.py @@ -18,18 +18,3 @@ except AttributeError: # Effectively skip subtests print(True) - -try: - raise SystemExit -except SystemExit as e: - print("SystemExit", e.args) - -try: - sys.exit() -except SystemExit as e: - print("SystemExit", e.args) - -try: - sys.exit(42) -except SystemExit as e: - print("SystemExit", e.args) diff --git a/tests/basics/sys_exit.py b/tests/basics/sys_exit.py new file mode 100644 index 0000000000000..b1f71549db1c5 --- /dev/null +++ b/tests/basics/sys_exit.py @@ -0,0 +1,24 @@ +# test sys module's exit function + +import sys + +try: + sys.exit +except AttributeError: + print("SKIP") + raise SystemExit + +try: + raise SystemExit +except SystemExit as e: + print("SystemExit", e.args) + +try: + sys.exit() +except SystemExit as e: + print("SystemExit", e.args) + +try: + sys.exit(42) +except SystemExit as e: + print("SystemExit", e.args) From 162016ad9c824df023e9870fd8d072e806d5ad96 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 22:23:00 +1100 Subject: [PATCH 0651/1299] travis: Add job to build and test unix minimal port. To test that unix minimal port builds, and that test-suite can run with minimal features enabled. --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5923cb2b96b8d..0f57bc3fe86b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -128,6 +128,13 @@ jobs: after_failure: - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) + # minimal unix port with tests + - stage: test + env: NAME="minimal unix port build and tests" + script: + - make ${MAKEOPTS} -C ports/unix minimal + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_minimal ./run-tests -e exception_chain -e self_type_check -e subclass_native_init -d basics) + # windows port via mingw - stage: test env: NAME="windows port build via mingw" From a8138b75b1d3ca8af01e4ad717c6cdb3f733c61d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 22:53:34 +1100 Subject: [PATCH 0652/1299] examples/embedding: Replace symlink of mpconfigport.h with real file. --- examples/embedding/mpconfigport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 120000 => 100644 examples/embedding/mpconfigport.h diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h deleted file mode 120000 index 142e5d6f4315c..0000000000000 --- a/examples/embedding/mpconfigport.h +++ /dev/null @@ -1 +0,0 @@ -mpconfigport_minimal.h \ No newline at end of file diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h new file mode 100644 index 0000000000000..89c180b2a8153 --- /dev/null +++ b/examples/embedding/mpconfigport.h @@ -0,0 +1 @@ +#include "mpconfigport_minimal.h" From 53f3cbc2c4f07236fe022c9c7af20b33443c60b1 Mon Sep 17 00:00:00 2001 From: Kamil Klimek Date: Fri, 25 Oct 2019 17:28:29 +0200 Subject: [PATCH 0653/1299] zephyr/main: Use mp_stack API instead of local pointer for stack top. The MP_STATE_THREAD(stack_top) is always available so use it instead of creating a separate variable. This also allows gc_collect() to be used as an independent function, without real_main() being called. --- ports/zephyr/main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ports/zephyr/main.c b/ports/zephyr/main.c index a28fb37923cf8..00dc71e28b9d6 100644 --- a/ports/zephyr/main.c +++ b/ports/zephyr/main.c @@ -48,7 +48,6 @@ #include TEST #endif -static char *stack_top; static char heap[MICROPY_HEAP_SIZE]; void init_zephyr(void) { @@ -79,9 +78,7 @@ void init_zephyr(void) { } int real_main(void) { - int stack_dummy; - stack_top = (char*)&stack_dummy; - mp_stack_set_top(stack_top); + mp_stack_ctrl_init(); // Make MicroPython's stack limit somewhat smaller than full stack available mp_stack_set_limit(CONFIG_MAIN_STACK_SIZE - 512); @@ -130,7 +127,7 @@ void gc_collect(void) { // pointers from CPU registers, and thus may function incorrectly. void *dummy; gc_collect_start(); - gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); + gc_collect_root(&dummy, ((mp_uint_t)MP_STATE_THREAD(stack_top) - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); gc_collect_end(); //gc_dump_info(); } From d16a27da5197e2369611bef4f18b47c183880510 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 28 Oct 2019 17:27:31 +1100 Subject: [PATCH 0654/1299] extmod/modbluetooth: Add gatts_set_buffer. - Adds an explicit way to set the size of a value's internal buffer, replacing `ble.gatts_write(handle, bytes(size))` (although that still works). - Add an "append" mode for values, which means that remote writes will append to the buffer. --- extmod/modbluetooth.c | 9 +++++++++ extmod/modbluetooth.h | 4 ++++ extmod/modbluetooth_nimble.c | 31 +++++++++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index d1a7d576e183f..1e5eafc89553a 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -557,6 +557,14 @@ STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify); +STATIC mp_obj_t bluetooth_ble_gatts_set_buffer(size_t n_args, const mp_obj_t *args) { + mp_int_t value_handle = mp_obj_get_int(args[1]); + mp_int_t len = mp_obj_get_int(args[2]); + bool append = n_args >= 4 && mp_obj_is_true(args[3]); + return bluetooth_handle_errno(mp_bluetooth_gatts_set_buffer(value_handle, len, append)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_set_buffer_obj, 3, 4, bluetooth_ble_gatts_set_buffer); + // ---------------------------------------------------------------------------- // Bluetooth object: GATTC (Central/Scanner role) // ---------------------------------------------------------------------------- @@ -626,6 +634,7 @@ STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_gatts_read), MP_ROM_PTR(&bluetooth_ble_gatts_read_obj) }, { MP_ROM_QSTR(MP_QSTR_gatts_write), MP_ROM_PTR(&bluetooth_ble_gatts_write_obj) }, { MP_ROM_QSTR(MP_QSTR_gatts_notify), MP_ROM_PTR(&bluetooth_ble_gatts_notify_obj) }, + { MP_ROM_QSTR(MP_QSTR_gatts_set_buffer), MP_ROM_PTR(&bluetooth_ble_gatts_set_buffer_obj) }, #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE // GATT Client (i.e. central/scanner role) { MP_ROM_QSTR(MP_QSTR_gattc_discover_services), MP_ROM_PTR(&bluetooth_ble_gattc_discover_services_obj) }, diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 20476b183c233..bce28a6d15526 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -183,6 +183,10 @@ int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, // Indicate the central. int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle); +// Resize and enable/disable append-mode on a value. +// Append-mode means that remote writes will append and local reads will clear after reading. +int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append); + // Disconnect from a central or peripheral. int mp_bluetooth_gap_disconnect(uint16_t conn_handle); diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 6287ca89ee8fb..33dac5a425caf 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -154,9 +154,14 @@ STATIC ble_addr_t create_nimble_addr(uint8_t addr_type, const uint8_t *addr) { #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE typedef struct { + // Pointer to heap-allocated data. uint8_t *data; + // Allocated size of data. size_t data_alloc; + // Current bytes in use. size_t data_len; + // Whether new writes append or replace existing data (default false). + bool append; } gatts_db_entry_t; volatile int mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF; @@ -206,6 +211,7 @@ STATIC void create_gatts_db_entry(uint16_t handle) { entry->data = m_new(uint8_t, MP_BLUETOOTH_MAX_ATTR_SIZE); entry->data_alloc = MP_BLUETOOTH_MAX_ATTR_SIZE; entry->data_len = 0; + entry->append = false; elem->value = MP_OBJ_FROM_PTR(entry); } @@ -430,8 +436,13 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, return BLE_ATT_ERR_ATTR_NOT_FOUND; } entry = MP_OBJ_TO_PTR(elem->value); - entry->data_len = MIN(entry->data_alloc, OS_MBUF_PKTLEN(ctxt->om)); - os_mbuf_copydata(ctxt->om, 0, entry->data_len, entry->data); + + size_t offset = 0; + if (entry->append) { + offset = entry->data_len; + } + entry->data_len = MIN(entry->data_alloc, OS_MBUF_PKTLEN(ctxt->om) + offset); + os_mbuf_copydata(ctxt->om, 0, entry->data_len - offset, entry->data + offset); mp_bluetooth_gatts_on_write(conn_handle, value_handle); @@ -547,6 +558,9 @@ int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *valu gatts_db_entry_t *entry = MP_OBJ_TO_PTR(elem->value); *value = entry->data; *value_len = entry->data_len; + if (entry->append) { + entry->data_len = 0; + } return 0; } @@ -587,6 +601,19 @@ int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle)); } +int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) { + mp_map_elem_t *elem = mp_map_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, MP_OBJ_NEW_SMALL_INT(value_handle), MP_MAP_LOOKUP); + if (!elem) { + return MP_EINVAL; + } + gatts_db_entry_t *entry = MP_OBJ_TO_PTR(elem->value); + entry->data = m_renew(uint8_t, entry->data, entry->data_alloc, len); + entry->data_alloc = len; + entry->data_len = 0; + entry->append = append; + return 0; +} + #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { From ca3d4c84e4722edefde586d7978f5a216c8febad Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 28 Oct 2019 17:29:08 +1100 Subject: [PATCH 0655/1299] docs/library/ubluetooth: Add docs for gatts_set_buffer. --- docs/library/ubluetooth.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index 831c64a95f859..5d44ffdb2943f 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -246,6 +246,17 @@ writes from a central to a given characteristic, use of the notification, avoiding the need for a separate read request. Note that this will not update the local value stored. +.. method:: BLE.gatts_set_buffer(value_handle, len, append=False) + + Sets the internal buffer size for a value in bytes. This will limit the + largest possible write that can be received. The default is 20. + + Setting *append* to ``True`` will make all remote writes append to, rather + than replace, the current value. At most *len* bytes can be buffered in + this way. When you use :meth:`gatts_read `, the value will + be cleared after reading. This feature is useful when implementing something + like the Nordic UART Service. + Central Role (GATT Client) -------------------------- From 25946d1ef4c20439368b37ec27acf2184b25be28 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 28 Oct 2019 17:33:29 +1100 Subject: [PATCH 0656/1299] examples/bluetooth/ble_uart_peripheral: Use append mode for RX char. --- examples/bluetooth/ble_uart_peripheral.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/bluetooth/ble_uart_peripheral.py b/examples/bluetooth/ble_uart_peripheral.py index 90cdbcaf526dd..14f7102725169 100644 --- a/examples/bluetooth/ble_uart_peripheral.py +++ b/examples/bluetooth/ble_uart_peripheral.py @@ -22,8 +22,8 @@ def __init__(self, ble, name='mpy-uart', rxbuf=100): self._ble.active(True) self._ble.irq(handler=self._irq) ((self._tx_handle, self._rx_handle,),) = self._ble.gatts_register_services((_UART_SERVICE,)) - # Increase the size of the rx buffer. - self._ble.gatts_write(self._rx_handle, bytes(rxbuf)) + # Increase the size of the rx buffer and enable append mode. + self._ble.gatts_set_buffer(self._rx_handle, rxbuf, True) self._connections = set() self._rx_buffer = bytearray() self._handler = None From 323d47887f0e407b6560a5957ea934049e70d2aa Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 12:08:07 +1100 Subject: [PATCH 0657/1299] py/runtime: Reorder some binary ops so they don't require conditionals. runtime0.h is part of the MicroPython ABI so it's simpler if it's independent of config options, like MICROPY_PY_REVERSE_SPECIAL_METHODS. What's effectively done here is to move MP_BINARY_OP_DIVMOD and MP_BINARY_OP_CONTAINS up in the enum, then remove the #if MICROPY_PY_REVERSE_SPECIAL_METHODS conditional. Without this change .mpy files would need to have a feature flag for MICROPY_PY_REVERSE_SPECIAL_METHODS (when embedding native code that uses this enum). This commit has no effect when MICROPY_PY_REVERSE_SPECIAL_METHODS is disabled. With this option enabled this commit reduces code size by about 60 bytes. --- py/runtime.c | 13 +++++++------ py/runtime0.h | 52 ++++++++++++++++++++++++++------------------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/py/runtime.c b/py/runtime.c index 6b7a9ce3c6e1c..deb82e9355096 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -570,16 +570,17 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } #if MICROPY_PY_REVERSE_SPECIAL_METHODS - if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_REVERSE_POWER) { + if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_POWER) { mp_obj_t t = rhs; rhs = lhs; lhs = t; - if (op <= MP_BINARY_OP_POWER) { - op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR; - goto generic_binary_op; - } - + op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR; + goto generic_binary_op; + } else if (op >= MP_BINARY_OP_REVERSE_OR) { // Convert __rop__ back to __op__ for error message + mp_obj_t t = rhs; + rhs = lhs; + lhs = t; op -= MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR; } #endif diff --git a/py/runtime0.h b/py/runtime0.h index 797ae00e60c75..364f237f66a6f 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -46,6 +46,18 @@ #define MP_NATIVE_TYPE_PTR16 (0x06) #define MP_NATIVE_TYPE_PTR32 (0x07) +// Bytecode and runtime boundaries for unary ops +#define MP_UNARY_OP_NUM_BYTECODE (MP_UNARY_OP_NOT + 1) +#define MP_UNARY_OP_NUM_RUNTIME (MP_UNARY_OP_SIZEOF + 1) + +// Bytecode and runtime boundaries for binary ops +#define MP_BINARY_OP_NUM_BYTECODE (MP_BINARY_OP_POWER + 1) +#if MICROPY_PY_REVERSE_SPECIAL_METHODS +#define MP_BINARY_OP_NUM_RUNTIME (MP_BINARY_OP_REVERSE_POWER + 1) +#else +#define MP_BINARY_OP_NUM_RUNTIME (MP_BINARY_OP_CONTAINS + 1) +#endif + typedef enum { // These ops may appear in the bytecode. Changing this group // in any way requires changing the bytecode version. @@ -55,21 +67,18 @@ typedef enum { MP_UNARY_OP_NOT, // Following ops cannot appear in the bytecode - MP_UNARY_OP_NUM_BYTECODE, - - MP_UNARY_OP_BOOL = MP_UNARY_OP_NUM_BYTECODE, // __bool__ + MP_UNARY_OP_BOOL, // __bool__ MP_UNARY_OP_LEN, // __len__ MP_UNARY_OP_HASH, // __hash__; must return a small int MP_UNARY_OP_ABS, // __abs__ MP_UNARY_OP_INT, // __int__ MP_UNARY_OP_SIZEOF, // for sys.getsizeof() - - MP_UNARY_OP_NUM_RUNTIME, } mp_unary_op_t; -// Note: the first 9+12+12 of these are used in bytecode and changing -// them requires changing the bytecode version. typedef enum { + // The following 9+13+13 ops are used in bytecode and changing + // them requires changing the bytecode version. + // 9 relational operations, should return a bool; order of first 6 matches corresponding mp_token_kind_t MP_BINARY_OP_LESS, MP_BINARY_OP_MORE, @@ -113,11 +122,18 @@ typedef enum { // Operations below this line don't appear in bytecode, they // just identify special methods. - MP_BINARY_OP_NUM_BYTECODE, - // MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_* -#if MICROPY_PY_REVERSE_SPECIAL_METHODS - MP_BINARY_OP_REVERSE_OR = MP_BINARY_OP_NUM_BYTECODE, + // This is not emitted by the compiler but is supported by the runtime. + // It must follow immediately after MP_BINARY_OP_POWER. + MP_BINARY_OP_DIVMOD, + + // The runtime will convert MP_BINARY_OP_IN to this operator with swapped args. + // A type should implement this containment operator instead of MP_BINARY_OP_IN. + MP_BINARY_OP_CONTAINS, + + // 13 MP_BINARY_OP_REVERSE_* operations must be in the same order as MP_BINARY_OP_*, + // and be the last ones supported by the runtime. + MP_BINARY_OP_REVERSE_OR, MP_BINARY_OP_REVERSE_XOR, MP_BINARY_OP_REVERSE_AND, MP_BINARY_OP_REVERSE_LSHIFT, @@ -130,20 +146,6 @@ typedef enum { MP_BINARY_OP_REVERSE_TRUE_DIVIDE, MP_BINARY_OP_REVERSE_MODULO, MP_BINARY_OP_REVERSE_POWER, -#endif - - // This is not emitted by the compiler but is supported by the runtime - MP_BINARY_OP_DIVMOD - #if !MICROPY_PY_REVERSE_SPECIAL_METHODS - = MP_BINARY_OP_NUM_BYTECODE - #endif - , - - // The runtime will convert MP_BINARY_OP_IN to this operator with swapped args. - // A type should implement this containment operator instead of MP_BINARY_OP_IN. - MP_BINARY_OP_CONTAINS, - - MP_BINARY_OP_NUM_RUNTIME, // These 2 are not supported by the runtime and must be synthesised by the emitter MP_BINARY_OP_NOT_IN, From 660a61a38830b67cb4f2b6f921d1db60f51c41a4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 30 Oct 2019 12:08:58 +1100 Subject: [PATCH 0658/1299] extmod/vfs_lfs: Allow compiling in VfsLfs1 and VfsLfs2 separately. These classes are enabled via the config options MICROPY_VFS_LFS1 and MICROPY_VFS_LFS2, which are disabled by default. --- extmod/extmod.mk | 15 +++++++++++---- extmod/vfs_lfs.c | 12 ++++++++++-- ports/unix/Makefile | 2 +- ports/unix/moduos_vfs.c | 4 +++- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/extmod/extmod.mk b/extmod/extmod.mk index 8e63b25f9081c..e714b602872dd 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -6,14 +6,21 @@ CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" ################################################################################ # VFS littlefs -ifeq ($(MICROPY_VFS_LFS),1) -CFLAGS_MOD += -DMICROPY_VFS_LFS=1 -CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT -CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT LITTLEFS_DIR = lib/littlefs + +ifeq ($(MICROPY_VFS_LFS1),1) +CFLAGS_MOD += -DMICROPY_VFS_LFS1=1 +CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ lfs1.c \ lfs1_util.c \ + ) +endif + +ifeq ($(MICROPY_VFS_LFS2),1) +CFLAGS_MOD += -DMICROPY_VFS_LFS2=1 +CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT +SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\ lfs2.c \ lfs2_util.c \ ) diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c index 72f501abbf42a..d776849980942 100644 --- a/extmod/vfs_lfs.c +++ b/extmod/vfs_lfs.c @@ -28,7 +28,7 @@ #include "extmod/vfs.h" #include "extmod/vfs_lfs.h" -#if MICROPY_VFS && MICROPY_VFS_LFS +#if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead }; @@ -39,6 +39,8 @@ static const mp_arg_t lfs_make_allowed_args[] = { { MP_QSTR_lookahead, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, }; +#if MICROPY_VFS_LFS1 + #include "lib/littlefs/lfs1.h" #define LFS_BUILD_VERSION (1) @@ -81,6 +83,10 @@ mp_obj_t mp_vfs_lfs1_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode #undef MP_TYPE_VFS_LFSx #undef MP_TYPE_VFS_LFSx_ +#endif // MICROPY_VFS_LFS1 + +#if MICROPY_VFS_LFS2 + #include "lib/littlefs/lfs2.h" #define LFS_BUILD_VERSION (2) @@ -114,4 +120,6 @@ mp_obj_t mp_vfs_lfs2_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode #include "extmod/vfs_lfsx.c" #include "extmod/vfs_lfsx_file.c" -#endif // MICROPY_VFS && MICROPY_VFS_LFS +#endif // MICROPY_VFS_LFS2 + +#endif // MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 5a21bd6b2a050..9a4453261cfc3 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -257,7 +257,7 @@ coverage: -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ -DMICROPY_UNIX_COVERAGE' \ LDFLAGS_EXTRA='-fprofile-arcs -ftest-coverage' \ - MICROPY_VFS_LFS=1 \ + MICROPY_VFS_LFS1=1 MICROPY_VFS_LFS2=1 \ FROZEN_MANIFEST=manifest_coverage.py \ BUILD=build-coverage PROG=micropython_coverage diff --git a/ports/unix/moduos_vfs.c b/ports/unix/moduos_vfs.c index 7abd0d150bc7c..7f38e6a8e059f 100644 --- a/ports/unix/moduos_vfs.c +++ b/ports/unix/moduos_vfs.c @@ -72,8 +72,10 @@ STATIC const mp_rom_map_elem_t uos_vfs_module_globals_table[] = { #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif - #if MICROPY_VFS_LFS + #if MICROPY_VFS_LFS1 { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, + #endif + #if MICROPY_VFS_LFS2 { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, #endif }; From 4e1b03d45c4d6be9ad9615f63a1146c46a4136d7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 30 Oct 2019 12:14:52 +1100 Subject: [PATCH 0659/1299] lib/libc/string0: Add simple implementations of strspn and strcspn. They are needed for littlefs. --- lib/libc/string0.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/libc/string0.c b/lib/libc/string0.c index c2f2abd0f95cc..8c86bf65f7b40 100644 --- a/lib/libc/string0.c +++ b/lib/libc/string0.c @@ -217,3 +217,19 @@ char *strstr(const char *haystack, const char *needle) return (char *) haystack; return 0; } + +size_t strspn(const char *s, const char *accept) { + const char *ss = s; + while (*s && strchr(accept, *s) != NULL) { + ++s; + } + return s - ss; +} + +size_t strcspn(const char *s, const char *reject) { + const char *ss = s; + while (*s && strchr(reject, *s) == NULL) { + ++s; + } + return s - ss; +} From 9ec73aedb4fedafce93a018c26cfbc79686be34b Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Oct 2019 12:49:18 +1100 Subject: [PATCH 0660/1299] stm32/timer: Fix Timer.freq() calc so mult doesn't overflow uint32_t. Fixes issue #5280. --- ports/stm32/timer.c | 20 +++++++++++++------- tests/pyb/timer.py | 6 ++++++ tests/pyb/timer.py.exp | 2 ++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 3b9f1dc400e9c..834ebd9c85ce0 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -1269,15 +1269,21 @@ STATIC mp_obj_t pyb_timer_freq(size_t n_args, const mp_obj_t *args) { uint32_t prescaler = self->tim.Instance->PSC & 0xffff; uint32_t period = __HAL_TIM_GET_AUTORELOAD(&self->tim) & TIMER_CNT_MASK(self); uint32_t source_freq = timer_get_source_freq(self->tim_id); - uint32_t divide = ((prescaler + 1) * (period + 1)); + uint32_t divide_a = prescaler + 1; + uint32_t divide_b = period + 1; #if MICROPY_PY_BUILTINS_FLOAT - if (source_freq % divide != 0) { - return mp_obj_new_float((float)source_freq / (float)divide); - } else - #endif - { - return mp_obj_new_int(source_freq / divide); + if (source_freq % divide_a != 0) { + return mp_obj_new_float((mp_float_t)source_freq / (mp_float_t)divide_a / (mp_float_t)divide_b); } + source_freq /= divide_a; + if (source_freq % divide_b != 0) { + return mp_obj_new_float((mp_float_t)source_freq / (mp_float_t)divide_b); + } else { + return mp_obj_new_int(source_freq / divide_b); + } + #else + return mp_obj_new_int(source_freq / divide_a / divide_b); + #endif } else { // set uint32_t period; diff --git a/tests/pyb/timer.py b/tests/pyb/timer.py index 61320690a6ccb..e83550abd8d9a 100644 --- a/tests/pyb/timer.py +++ b/tests/pyb/timer.py @@ -11,3 +11,9 @@ print(tim.prescaler()) tim.period(400) print(tim.period()) + +# Setting and printing frequency +tim = Timer(2, freq=100) +print(tim.freq()) +tim.freq(0.001) +print(tim.freq()) diff --git a/tests/pyb/timer.py.exp b/tests/pyb/timer.py.exp index 5c46230303de4..7602bbd70dbd2 100644 --- a/tests/pyb/timer.py.exp +++ b/tests/pyb/timer.py.exp @@ -2,3 +2,5 @@ 200 300 400 +100 +0.001 From 71401d5065e20da59a1cc740d760002794b008e0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 16 Oct 2019 16:26:20 +1100 Subject: [PATCH 0661/1299] extmod/modlwip: Unconditionally return POLLHUP when polling new socket. POSIX poll should always return POLLERR and POLLHUP in revents, regardless of whether they were requested in the input events flags. See issues #4290 and #5172. --- extmod/modlwip.c | 2 +- tests/net_hosted/connect_poll.py | 3 +-- tests/net_hosted/connect_poll.py.exp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 050937750aaca..cd0f6946cd6bb 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1468,7 +1468,7 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ if (socket->state == STATE_NEW) { // New sockets are not connected so set HUP - ret |= flags & MP_STREAM_POLL_HUP; + ret |= MP_STREAM_POLL_HUP; } else if (socket->state == STATE_PEER_CLOSED) { // Peer-closed socket is both readable and writable: read will // return EOF, write - error. Without this poll will hang on a diff --git a/tests/net_hosted/connect_poll.py b/tests/net_hosted/connect_poll.py index ece6aa0da9721..7aeba8f6d417f 100644 --- a/tests/net_hosted/connect_poll.py +++ b/tests/net_hosted/connect_poll.py @@ -12,9 +12,8 @@ def test(peer_addr): poller.register(s) # test poll before connect - # note: CPython can return POLLHUP, so use the IN|OUT mask p = poller.poll(0) - print(len(p), p[0][-1] & (select.POLLIN | select.POLLOUT)) + print(len(p), p[0][-1]) s.connect(peer_addr) diff --git a/tests/net_hosted/connect_poll.py.exp b/tests/net_hosted/connect_poll.py.exp index cdf520e090bb7..d18a39a12a813 100644 --- a/tests/net_hosted/connect_poll.py.exp +++ b/tests/net_hosted/connect_poll.py.exp @@ -1,3 +1,3 @@ -1 4 +1 20 1 1 4 From d3c383de79bd25b42339cc7a4c68b79e39eccc7c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 16 Oct 2019 17:24:19 +1100 Subject: [PATCH 0662/1299] py/stream.h: Add MP_STREAM_POLL_NVAL constant. --- py/stream.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/py/stream.h b/py/stream.h index b6019bb38a543..3ebd4e0421bf1 100644 --- a/py/stream.h +++ b/py/stream.h @@ -45,10 +45,11 @@ #define MP_STREAM_GET_FILENO (10) // Get fileno of underlying file // These poll ioctl values are compatible with Linux -#define MP_STREAM_POLL_RD (0x0001) -#define MP_STREAM_POLL_WR (0x0004) -#define MP_STREAM_POLL_ERR (0x0008) -#define MP_STREAM_POLL_HUP (0x0010) +#define MP_STREAM_POLL_RD (0x0001) +#define MP_STREAM_POLL_WR (0x0004) +#define MP_STREAM_POLL_ERR (0x0008) +#define MP_STREAM_POLL_HUP (0x0010) +#define MP_STREAM_POLL_NVAL (0x0020) // Argument structure for MP_STREAM_SEEK struct mp_stream_seek_t { From feaa2516742ed4f9032a0233dcec922ac6a4e80c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 16 Oct 2019 17:24:40 +1100 Subject: [PATCH 0663/1299] extmod/modlwip: Make socket poll return POLLNVAL in case of bad file. --- extmod/modlwip.c | 2 ++ tests/extmod/uselect_poll_basic.py | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index cd0f6946cd6bb..1e9b8c4590e3d 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1477,6 +1477,8 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ } else if (socket->state == ERR_RST) { // Socket was reset by peer, a write will return an error ret |= flags & (MP_STREAM_POLL_WR | MP_STREAM_POLL_HUP); + } else if (socket->state == _ERR_BADF) { + ret |= MP_STREAM_POLL_NVAL; } else if (socket->state < 0) { // Socket in some other error state, use catch-all ERR flag // TODO: may need to set other return flags here diff --git a/tests/extmod/uselect_poll_basic.py b/tests/extmod/uselect_poll_basic.py index df52471ac3992..82a7195c03b2a 100644 --- a/tests/extmod/uselect_poll_basic.py +++ b/tests/extmod/uselect_poll_basic.py @@ -33,3 +33,9 @@ poller.modify(s, select.POLLIN) except OSError as e: assert e.args[0] == errno.ENOENT + +# poll after closing the socket, should return POLLNVAL +poller.register(s) +s.close() +p = poller.poll(0) +print(len(p), p[0][-1]) From 26d8fd2c0a1385a7c22363ea0695e6a0c828dc8d Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 16 Oct 2019 17:34:11 +1100 Subject: [PATCH 0664/1299] extmod/modlwip: Unconditionally return POLLHUP/POLLERR when polling. POSIX poll should always return POLLERR and POLLHUP in revents, regardless of whether they were requested in the input events flags. See issues #4290 and #5172. --- extmod/modlwip.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 1e9b8c4590e3d..4358544bab58b 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1476,13 +1476,14 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR); } else if (socket->state == ERR_RST) { // Socket was reset by peer, a write will return an error - ret |= flags & (MP_STREAM_POLL_WR | MP_STREAM_POLL_HUP); + ret |= flags & MP_STREAM_POLL_WR; + ret |= MP_STREAM_POLL_HUP; } else if (socket->state == _ERR_BADF) { ret |= MP_STREAM_POLL_NVAL; } else if (socket->state < 0) { // Socket in some other error state, use catch-all ERR flag // TODO: may need to set other return flags here - ret |= flags & MP_STREAM_POLL_ERR; + ret |= MP_STREAM_POLL_ERR; } } else if (request == MP_STREAM_CLOSE) { From 07ea81fbc57dc52c52de32ab4088fe7e29de4e0d Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Oct 2019 13:42:24 +1100 Subject: [PATCH 0665/1299] extmod/modussl_mbedtls: Fix getpeercert to return None if no cert avail. --- extmod/modussl_mbedtls.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 6759f11fa5d69..4105d3fa02453 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -219,6 +219,9 @@ STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) { mp_raise_NotImplementedError(NULL); } const mbedtls_x509_crt* peer_cert = mbedtls_ssl_get_peer_cert(&o->ssl); + if (peer_cert == NULL) { + return mp_const_none; + } return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert); From 9dd9f9ff06c15b06b4b35959196610d5cb952cf0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Oct 2019 16:22:42 +1100 Subject: [PATCH 0666/1299] extmod/modussl_mbedtls: Check for invalid key/cert data. --- extmod/modussl_mbedtls.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 4105d3fa02453..a71adc5b366da 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -169,21 +169,29 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL); - if (args->key.u_obj != MP_OBJ_NULL) { + if (args->key.u_obj != mp_const_none) { size_t key_len; const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len); // len should include terminating null ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0); - assert(ret == 0); + if (ret != 0) { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; // use general error for all key errors + goto cleanup; + } size_t cert_len; const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len); // len should include terminating null ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1); - assert(ret == 0); + if (ret != 0) { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors + goto cleanup; + } ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey); - assert(ret == 0); + if (ret != 0) { + goto cleanup; + } } if (args->do_handshake.u_bool) { @@ -208,6 +216,10 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { mp_raise_OSError(MP_ENOMEM); + } else if (ret == MBEDTLS_ERR_PK_BAD_INPUT_DATA) { + mp_raise_ValueError("invalid key"); + } else if (ret == MBEDTLS_ERR_X509_BAD_INPUT_DATA) { + mp_raise_ValueError("invalid cert"); } else { mp_raise_OSError(MP_EIO); } @@ -334,8 +346,8 @@ STATIC const mp_obj_type_t ussl_socket_type = { STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Implement more args static const mp_arg_t allowed_args[] = { - { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, From 43f53a2bbd4668dc196ebda5d0ccc1aa37312418 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 31 Oct 2019 16:38:20 +1100 Subject: [PATCH 0667/1299] tests/extmod: Add test for ussl when passing in key/cert params. --- tests/extmod/ussl_keycert.py | 28 ++++++++++++++++++++++++++++ tests/extmod/ussl_keycert.py.exp | 3 +++ 2 files changed, 31 insertions(+) create mode 100644 tests/extmod/ussl_keycert.py create mode 100644 tests/extmod/ussl_keycert.py.exp diff --git a/tests/extmod/ussl_keycert.py b/tests/extmod/ussl_keycert.py new file mode 100644 index 0000000000000..9b3eae60274f8 --- /dev/null +++ b/tests/extmod/ussl_keycert.py @@ -0,0 +1,28 @@ +# Test ussl with key/cert passed in + +try: + import uio as io + import ussl as ssl +except ImportError: + print("SKIP") + raise SystemExit + +key = b'0\x82\x019\x02\x01\x00\x02A\x00\xf9\xe0}\xbd\xd7\x9cI\x18\x06\xc3\xcb\xb5\xec@r\xfbD\x18\x80\xaaWoZ{\xcc\xa3\xeb!"\x0fY\x9e]-\xee\xe4\t!BY\x9f{7\xf3\xf2\x8f}}\r|.\xa8<\ta\xb2\xd7W\xb3\xc9\x19A\xc39\x02\x03\x01\x00\x01\x02@\x07:\x9fh\xa6\x9c6\xe1#\x10\xf7\x0b\xc4Q\xf9\x01\x9b\xee\xb9\x8a4\r\\\xa8\xc8:\xd5\xca\x97\x99\xaa\x16\x04)\xa8\xf9\x13\xdeq\x0ev`\xa7\x83\xc5\x8b`\xdb\xef \x9d\x93\xe8g\x84\x96\xfaV\\\xf4R\xda\xd0\xa1\x02!\x00\xfeR\xbf\n\x91Su\x87L\x98{\xeb%\xed\xfb\x06u)@\xfe\x1b\xde\xa0\xc6@\xab\xc5\xedg\x8e\x10[\x02!\x00\xfb\x86=\x85\xa4\'\xde\x85\xb5L\xe0)\x99\xfaL\x8c3A\x02\xa8<\xdew\xad\x00\xe3\x1d\x05\xd8\xb4N\xfb\x02 \x08\xb0M\x04\x90hx\x88q\xcew\xd5U\xcbf\x9b\x16\xdf\x9c\xef\xd1\x85\xee\x9a7Ug\x02\xb0Z\x03\'\x02 9\xa0D\xe2$|\xf9\xefz]5\x92rs\xb5+\xfd\xe6,\x1c\xadmn\xcf\xd5?3|\x0em)\x17\x02 5Z\xcc/\xa5?\n\x04%\x9b{N\x9dX\xddI\xbe\xd2\xb0\xa0\x03BQ\x02\x82\xc2\xe0u)\xbd\xb8\xaf' + +# Invalid key +try: + ssl.wrap_socket(io.BytesIO(), key=b'!') +except ValueError as er: + print(repr(er)) + +# Valid key, no cert +try: + ssl.wrap_socket(io.BytesIO(), key=key) +except TypeError as er: + print(repr(er)) + +# Valid key, invalid cert +try: + ssl.wrap_socket(io.BytesIO(), key=key, cert=b'!') +except ValueError as er: + print(repr(er)) diff --git a/tests/extmod/ussl_keycert.py.exp b/tests/extmod/ussl_keycert.py.exp new file mode 100644 index 0000000000000..b72d319c6a807 --- /dev/null +++ b/tests/extmod/ussl_keycert.py.exp @@ -0,0 +1,3 @@ +ValueError('invalid key',) +TypeError("can't convert 'NoneType' object to str implicitly",) +ValueError('invalid cert',) From a5d97f1db95fff3c33fbb69300ad7e31cb6d0dd1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 23 Oct 2019 16:56:14 +1100 Subject: [PATCH 0668/1299] stm32: Add soft timer implementation, using SysTick at 1ms resolution. This commit adds an implementation of a "software timer" with a 1ms resolution, using SysTick. It allows unlimited number of concurrent timers (limited only by memory needed for each timer entry). They can be one-shot or periodic, and associated with a Python callback. There is a very small overhead added to the SysTick IRQ, which could be further optimised in the future, eg by patching SysTick_Handler code dynamically. --- ports/stm32/Makefile | 1 + ports/stm32/main.c | 2 + ports/stm32/mpconfigport.h | 2 + ports/stm32/pendsv.h | 3 +- ports/stm32/softtimer.c | 112 +++++++++++++++++++++++++++++++++++++ ports/stm32/softtimer.h | 50 +++++++++++++++++ ports/stm32/systick.c | 6 ++ 7 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 ports/stm32/softtimer.c create mode 100644 ports/stm32/softtimer.h diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index fca92f841eddc..82711eca62ecf 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -249,6 +249,7 @@ SRC_C = \ irq.c \ pendsv.c \ systick.c \ + softtimer.c \ powerctrl.c \ powerctrlboot.c \ pybthread.c \ diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 685dbd10c7b1f..a00bdf3bdbfa1 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -55,6 +55,7 @@ #include "gccollect.h" #include "factoryreset.h" #include "modmachine.h" +#include "softtimer.h" #include "i2c.h" #include "spi.h" #include "uart.h" @@ -743,6 +744,7 @@ void stm32_main(uint32_t reset_mode) { #if MICROPY_PY_NETWORK mod_network_deinit(); #endif + soft_timer_deinit(); timer_deinit(); uart_deinit_all(); #if MICROPY_HW_ENABLE_CAN diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index b31eed29326f2..11c23723854a9 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -282,6 +282,8 @@ struct _mp_bluetooth_nimble_root_pointers_t; \ mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ \ + struct _soft_timer_entry_t *soft_timer_head; \ + \ /* pointers to all Timer objects (if they have been created) */ \ struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \ \ diff --git a/ports/stm32/pendsv.h b/ports/stm32/pendsv.h index 9851a5ece7b9c..dd3f8f2cb38b8 100644 --- a/ports/stm32/pendsv.h +++ b/ports/stm32/pendsv.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_STM32_PENDSV_H enum { + PENDSV_DISPATCH_SOFT_TIMER, #if MICROPY_PY_NETWORK && MICROPY_PY_LWIP PENDSV_DISPATCH_LWIP, #if MICROPY_PY_NETWORK_CYW43 @@ -39,9 +40,7 @@ enum { PENDSV_DISPATCH_MAX }; -#if (MICROPY_PY_NETWORK && MICROPY_PY_LWIP) || (MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE) #define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX -#endif typedef void (*pendsv_dispatch_t)(void); diff --git a/ports/stm32/softtimer.c b/ports/stm32/softtimer.c new file mode 100644 index 0000000000000..c598bac1779c7 --- /dev/null +++ b/ports/stm32/softtimer.c @@ -0,0 +1,112 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include "py/runtime.h" +#include "irq.h" +#include "softtimer.h" + +#define TICKS_PERIOD 0x80000000 +#define TICKS_DIFF(t1, t0) ((int32_t)(((t1 - t0 + TICKS_PERIOD / 2) & (TICKS_PERIOD - 1)) - TICKS_PERIOD / 2)) + +extern __IO uint32_t uwTick; + +volatile uint32_t soft_timer_next; + +void soft_timer_deinit(void) { + MP_STATE_PORT(soft_timer_head) = NULL; +} + +STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { + uint32_t irq_state = disable_irq(); + uint32_t uw_tick = uwTick; + if (TICKS_DIFF(ticks_ms, uw_tick) <= 0) { + soft_timer_next = uw_tick + 1; + } else { + soft_timer_next = ticks_ms; + } + enable_irq(irq_state); +} + +// Must be executed at IRQ_PRI_PENDSV +void soft_timer_handler(void) { + uint32_t ticks_ms = uwTick; + soft_timer_entry_t *head = MP_STATE_PORT(soft_timer_head); + while (head != NULL && TICKS_DIFF(head->expiry_ms, ticks_ms) <= 0) { + mp_sched_schedule(head->callback, MP_OBJ_FROM_PTR(head)); + if (head->mode == SOFT_TIMER_MODE_PERIODIC) { + head->expiry_ms += head->delta_ms; + // Shift this node along to its new position + soft_timer_entry_t *cur = head; + while (cur->next != NULL && TICKS_DIFF(head->expiry_ms, cur->next->expiry_ms) >= 0) { + cur = cur->next; + } + if (cur != head) { + soft_timer_entry_t *next = head->next; + head->next = cur->next; + cur->next = head; + head = next; + } + } else { + head = head->next; + } + } + MP_STATE_PORT(soft_timer_head) = head; + if (head == NULL) { + // No more timers left, set largest delay possible + soft_timer_next = uwTick; + } else { + // Set soft_timer_next so SysTick calls us back at the correct time + soft_timer_schedule_systick(head->expiry_ms); + } +} + +void soft_timer_insert(soft_timer_entry_t *entry) { + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + soft_timer_entry_t **head_ptr = &MP_STATE_PORT(soft_timer_head); + while (*head_ptr != NULL && TICKS_DIFF(entry->expiry_ms, (*head_ptr)->expiry_ms) >= 0) { + head_ptr = &(*head_ptr)->next; + } + entry->next = *head_ptr; + *head_ptr = entry; + if (head_ptr == &MP_STATE_PORT(soft_timer_head)) { + // This new timer became the earliest one so set soft_timer_next + soft_timer_schedule_systick((*head_ptr)->expiry_ms); + } + restore_irq_pri(irq_state); +} + +void soft_timer_remove(soft_timer_entry_t *entry) { + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + soft_timer_entry_t **cur = &MP_STATE_PORT(soft_timer_head); + while (*cur != NULL) { + if (*cur == entry) { + *cur = entry->next; + break; + } + } + restore_irq_pri(irq_state); +} diff --git a/ports/stm32/softtimer.h b/ports/stm32/softtimer.h new file mode 100644 index 0000000000000..2550446d832e9 --- /dev/null +++ b/ports/stm32/softtimer.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_SOFTTIMER_H +#define MICROPY_INCLUDED_STM32_SOFTTIMER_H + +#include "py/obj.h" + +#define SOFT_TIMER_MODE_ONE_SHOT (1) +#define SOFT_TIMER_MODE_PERIODIC (2) + +typedef struct _soft_timer_entry_t { + mp_obj_base_t base; // so struct can be used as an object and still be traced by GC + struct _soft_timer_entry_t *next; + uint32_t mode; + uint32_t expiry_ms; + uint32_t delta_ms; // for periodic mode + mp_obj_t callback; +} soft_timer_entry_t; + +extern volatile uint32_t soft_timer_next; + +void soft_timer_deinit(void); +void soft_timer_handler(void); +void soft_timer_insert(soft_timer_entry_t *entry); +void soft_timer_remove(soft_timer_entry_t *entry); + +#endif // MICROPY_INCLUDED_STM32_SOFTTIMER_H diff --git a/ports/stm32/systick.c b/ports/stm32/systick.c index d92f9d75dcf62..85c99b9aebddc 100644 --- a/ports/stm32/systick.c +++ b/ports/stm32/systick.c @@ -27,7 +27,9 @@ #include "py/runtime.h" #include "py/mphal.h" #include "irq.h" +#include "pendsv.h" #include "systick.h" +#include "softtimer.h" #include "pybthread.h" extern __IO uint32_t uwTick; @@ -52,6 +54,10 @@ void SysTick_Handler(void) { f(uw_tick); } + if (soft_timer_next == uw_tick) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); + } + #if MICROPY_PY_THREAD if (pyb_thread_enabled) { if (pyb_thread_cur->timeslice == 0) { From 48b25a841b04108d4dc399fad87b413f9f52c6bb Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 23 Oct 2019 16:56:38 +1100 Subject: [PATCH 0669/1299] stm32: Add machine.Timer with soft timer implementation. This commit adds an implementation of machine.Timer backed by the soft timer mechanism. It allows an arbitrary number of timers with 1ms resolution, with an associated Python callback. The Python-level API matches existing ports that have a soft timer, and is used as: from machine import Timer t = Timer(freq=10, callback=lambda t:print(t)) ... t = Timer(mode=Timer.ONE_SHOT, period=2000, callback=lambda t:print(t)) ... t.deinit() --- ports/stm32/Makefile | 1 + ports/stm32/machine_timer.c | 132 ++++++++++++++++++++++++++++++++++++ ports/stm32/modmachine.c | 2 +- ports/stm32/modmachine.h | 1 + 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 ports/stm32/machine_timer.c diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 82711eca62ecf..2a3b14d046549 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -278,6 +278,7 @@ SRC_C = \ machine_adc.c \ machine_i2c.c \ machine_spi.c \ + machine_timer.c \ machine_uart.c \ modmachine.c \ modpyb.c \ diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c new file mode 100644 index 0000000000000..49e3a54d01a7d --- /dev/null +++ b/ports/stm32/machine_timer.c @@ -0,0 +1,132 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" +#include "softtimer.h" + +typedef soft_timer_entry_t machine_timer_obj_t; + +const mp_obj_type_t machine_timer_type; + +STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_timer_obj_t *self = self_in; + qstr mode = self->mode == SOFT_TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC; + mp_printf(print, "Timer(mode=%q, period=%u)", mode, self->delta_ms); +} + +STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SOFT_TIMER_MODE_PERIODIC} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, + { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + // Parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + self->mode = args[ARG_mode].u_int; + if (args[ARG_freq].u_obj != mp_const_none) { + // Frequency specified in Hz + #if MICROPY_PY_BUILTINS_FLOAT + self->delta_ms = 1000 / mp_obj_get_float(args[ARG_freq].u_obj); + #else + self->delta_ms = 1000 / mp_obj_get_int(args[ARG_freq].u_obj); + #endif + } else { + // Period specified + self->delta_ms = args[ARG_period].u_int * 1000 / args[ARG_tick_hz].u_int; + } + if (self->delta_ms < 1) { + self->delta_ms = 1; + } + self->expiry_ms = mp_hal_ticks_ms() + self->delta_ms; + + self->callback = args[ARG_callback].u_obj; + soft_timer_insert(self); + + return mp_const_none; +} + +STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); + self->base.type = &machine_timer_type; + + // Get timer id (only soft timer (-1) supported at the moment) + mp_int_t id = -1; + if (n_args > 0) { + id = mp_obj_get_int(args[0]); + --n_args; + ++args; + } + if (id != -1) { + mp_raise_ValueError("Timer doesn't exist"); + } + + if (n_args > 0 || n_kw > 0) { + // Start the timer + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_timer_init_helper(self, n_args, args, &kw_args); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]); + soft_timer_remove(self); + return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init); + +STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) { + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); + soft_timer_remove(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit); + +STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(SOFT_TIMER_MODE_ONE_SHOT) }, + { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(SOFT_TIMER_MODE_PERIODIC) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table); + +const mp_obj_type_t machine_timer_type = { + { &mp_type_type }, + .name = MP_QSTR_Timer, + .print = machine_timer_print, + .make_new = machine_timer_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_timer_locals_dict, +}; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index eaa536a1db802..7db8e29643c47 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -399,8 +399,8 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&pyb_wdt_type) }, + { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, #if 0 - { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) }, { MP_ROM_QSTR(MP_QSTR_HeartBeat), MP_ROM_PTR(&pyb_heartbeat_type) }, { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sd_type) }, diff --git a/ports/stm32/modmachine.h b/ports/stm32/modmachine.h index 4b727d3cb9d8a..f04bfb486bb81 100644 --- a/ports/stm32/modmachine.h +++ b/ports/stm32/modmachine.h @@ -29,6 +29,7 @@ #include "py/obj.h" extern const mp_obj_type_t machine_adc_type; +extern const mp_obj_type_t machine_timer_type; void machine_init(void); void machine_deinit(void); From 78145b98ef6c755c5cf7745ea643766bec6f9045 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Nov 2019 12:15:07 +1100 Subject: [PATCH 0670/1299] extmod/nimble: Remove unneeded nimble_sprintf wrapper function. --- extmod/nimble/nimble.mk | 1 - extmod/nimble/nimble/misc.c | 44 ------------------------------------- 2 files changed, 45 deletions(-) delete mode 100644 extmod/nimble/nimble/misc.c diff --git a/extmod/nimble/nimble.mk b/extmod/nimble/nimble.mk index 274fcdb9f34f4..e554e9ff0619f 100644 --- a/extmod/nimble/nimble.mk +++ b/extmod/nimble/nimble.mk @@ -72,7 +72,6 @@ SRC_LIB += $(addprefix $(NIMBLE_LIB_DIR)/, \ ) EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \ - nimble/misc.c \ nimble/npl_os.c \ nimble/hci_uart.c \ ) diff --git a/extmod/nimble/nimble/misc.c b/extmod/nimble/nimble/misc.c deleted file mode 100644 index 0e7d8a42a8963..0000000000000 --- a/extmod/nimble/nimble/misc.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018-2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/runtime.h" - -#if MICROPY_BLUETOOTH_NIMBLE - -/******************************************************************************/ -// Misc functions needed by Nimble - -#include - -int nimble_sprintf(char *str, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - int ret = vsnprintf(str, 65535, fmt, ap); - va_end(ap); - return ret; -} - -#endif From 40ea1915fc06b7abc4fac6649c70f9b89dc51e2b Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Nov 2019 12:41:37 +1100 Subject: [PATCH 0671/1299] extmod/nimble: Factor out stm32-specific HCI UART RX/TX code. --- extmod/nimble/nimble/hci_uart.c | 36 +------------------------ extmod/nimble/nimble/hci_uart.h | 5 ++-- ports/stm32/nimble_hci_uart.c | 47 +++++++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 42 deletions(-) diff --git a/extmod/nimble/nimble/hci_uart.c b/extmod/nimble/nimble/hci_uart.c index 801291def4650..b4ac4e738828e 100644 --- a/extmod/nimble/nimble/hci_uart.c +++ b/extmod/nimble/nimble/hci_uart.c @@ -42,8 +42,6 @@ static void *hal_uart_tx_arg; static hal_uart_rx_cb_t hal_uart_rx_cb; static void *hal_uart_rx_arg; -static uint32_t bt_sleep_ticks; - int hal_uart_init_cbs(uint32_t port, hal_uart_tx_cb_t tx_cb, void *tx_arg, hal_uart_rx_cb_t rx_cb, void *rx_arg) { hal_uart_tx_cb = tx_cb; hal_uart_tx_arg = tx_arg; @@ -76,16 +74,6 @@ void hal_uart_start_tx(uint32_t port) { printf("\n"); #endif - bt_sleep_ticks = mp_hal_ticks_ms(); - - #ifdef pyb_pin_BT_DEV_WAKE - if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) { - //printf("BT WAKE for TX\n"); - mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up - mp_hal_delay_ms(5); // can't go lower than this - } - #endif - nimble_hci_uart_tx_strn((void*)bt_hci_cmd_buf, len); } @@ -94,29 +82,7 @@ int hal_uart_close(uint32_t port) { } void nimble_uart_process(void) { - int host_wake = 0; - #ifdef pyb_pin_BT_HOST_WAKE - host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE); - #endif - /* - // this is just for info/tracing purposes - static int last_host_wake = 0; - if (host_wake != last_host_wake) { - printf("HOST_WAKE change %d -> %d\n", last_host_wake, host_wake); - last_host_wake = host_wake; - } - */ - while (nimble_hci_uart_rx_any()) { - uint8_t data = nimble_hci_uart_rx_char(); - //printf("UART RX: %02x\n", data); - hal_uart_rx_cb(hal_uart_rx_arg, data); - } - if (host_wake == 1 && mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) { - if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) { - //printf("BT SLEEP\n"); - mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep - } - } + nimble_hci_uart_rx(hal_uart_rx_cb, hal_uart_rx_arg); } #endif // MICROPY_BLUETOOTH_NIMBLE diff --git a/extmod/nimble/nimble/hci_uart.h b/extmod/nimble/nimble/hci_uart.h index e184210830b89..3d4a2a9835f17 100644 --- a/extmod/nimble/nimble/hci_uart.h +++ b/extmod/nimble/nimble/hci_uart.h @@ -26,6 +26,8 @@ #ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H #define MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H +#include "extmod/nimble/hal/hal_uart.h" + // To be implemented by the port. int nimble_hci_uart_configure(uint32_t port); @@ -35,8 +37,7 @@ int nimble_hci_uart_set_baudrate(uint32_t baudrate); int nimble_hci_uart_activate(void); -mp_uint_t nimble_hci_uart_rx_any(); -int nimble_hci_uart_rx_char(); +void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg); void nimble_hci_uart_tx_strn(const char *str, uint len); #endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H diff --git a/ports/stm32/nimble_hci_uart.c b/ports/stm32/nimble_hci_uart.c index 104a64b732838..251f15e3b4a01 100644 --- a/ports/stm32/nimble_hci_uart.c +++ b/ports/stm32/nimble_hci_uart.c @@ -28,6 +28,7 @@ #include "py/mphal.h" #include "uart.h" #include "pendsv.h" +#include "extmod/nimble/nimble/hci_uart.h" #include "drivers/cyw43/cywbt.h" #if MICROPY_BLUETOOTH_NIMBLE @@ -37,6 +38,10 @@ pyb_uart_obj_t bt_hci_uart_obj; static uint8_t hci_uart_rxbuf[512]; +#ifdef pyb_pin_BT_DEV_WAKE +static uint32_t bt_sleep_ticks; +#endif + extern void nimble_poll(void); mp_obj_t mp_uart_interrupt(mp_obj_t self_in) { @@ -81,15 +86,47 @@ int nimble_hci_uart_activate(void) { return 0; } -mp_uint_t nimble_hci_uart_rx_any() { - return uart_rx_any(&bt_hci_uart_obj); -} +void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) { + #ifdef pyb_pin_BT_HOST_WAKE + int host_wake = 0; + host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE); + /* + // this is just for info/tracing purposes + static int last_host_wake = 0; + if (host_wake != last_host_wake) { + printf("HOST_WAKE change %d -> %d\n", last_host_wake, host_wake); + last_host_wake = host_wake; + } + */ + #endif + + while (uart_rx_any(&bt_hci_uart_obj)) { + uint8_t data = uart_rx_char(&bt_hci_uart_obj); + //printf("UART RX: %02x\n", data); + rx_cb(rx_arg, data); + } -int nimble_hci_uart_rx_char() { - return uart_rx_char(&bt_hci_uart_obj); + #ifdef pyb_pin_BT_DEV_WAKE + if (host_wake == 1 && mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) { + if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) { + //printf("BT SLEEP\n"); + mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep + } + } + #endif } void nimble_hci_uart_tx_strn(const char *str, uint len) { + #ifdef pyb_pin_BT_DEV_WAKE + bt_sleep_ticks = mp_hal_ticks_ms(); + + if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) { + //printf("BT WAKE for TX\n"); + mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up + mp_hal_delay_ms(5); // can't go lower than this + } + #endif + uart_tx_strn(&bt_hci_uart_obj, str, len); } From 6a64b280d03755ecb0c58f42f6b649e931fd2018 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Nov 2019 14:52:17 +1100 Subject: [PATCH 0672/1299] stm32: Add support for RF coprocessor on WB55 MCUs. This requires a BLE wireless stack firmware to be already programmed in the secure flash area of the device. --- ports/stm32/Makefile | 1 + ports/stm32/boards/stm32wb55xg.ld | 11 + ports/stm32/main.c | 4 + ports/stm32/nimble_hci_uart.c | 49 +++- ports/stm32/rfcore.c | 425 ++++++++++++++++++++++++++++++ ports/stm32/rfcore.h | 37 +++ 6 files changed, 523 insertions(+), 4 deletions(-) create mode 100644 ports/stm32/rfcore.c create mode 100644 ports/stm32/rfcore.h diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 2a3b14d046549..99d2248fd4086 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -252,6 +252,7 @@ SRC_C = \ softtimer.c \ powerctrl.c \ powerctrlboot.c \ + rfcore.c \ pybthread.c \ factoryreset.c \ timer.c \ diff --git a/ports/stm32/boards/stm32wb55xg.ld b/ports/stm32/boards/stm32wb55xg.ld index bdbf7e447e1d3..77596d7759689 100644 --- a/ports/stm32/boards/stm32wb55xg.ld +++ b/ports/stm32/boards/stm32wb55xg.ld @@ -8,6 +8,7 @@ MEMORY FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* sectors 0-127 */ FLASH_FS (r) : ORIGIN = 0x08080000, LENGTH = 256K /* sectors 128-191 */ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K /* SRAM1 */ + RAM2A (xrw) : ORIGIN = 0x20030020, LENGTH = 8K /* SRAM2A */ } /* produce a link error if there is not this amount of RAM for these sections */ @@ -31,3 +32,13 @@ _heap_end = _sstack; _flash_fs_start = ORIGIN(FLASH_FS); _flash_fs_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); + +SECTIONS +{ + .ram2a_bss : + { + . = ALIGN(4); + *rfcore.o(.bss.ipcc_mem_*) + . = ALIGN(4); + } >RAM2A +} diff --git a/ports/stm32/main.c b/ports/stm32/main.c index a00bdf3bdbfa1..3c6420d50d551 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -48,6 +48,7 @@ #endif #include "mpu.h" +#include "rfcore.h" #include "systick.h" #include "pendsv.h" #include "powerctrl.h" @@ -466,6 +467,9 @@ void stm32_main(uint32_t reset_mode) { #endif // basic sub-system init + #if defined(STM32WB) + rfcore_init(); + #endif #if MICROPY_HW_SDRAM_SIZE sdram_init(); #if MICROPY_HW_SDRAM_STARTUP_TEST diff --git a/ports/stm32/nimble_hci_uart.c b/ports/stm32/nimble_hci_uart.c index 251f15e3b4a01..defda1581e064 100644 --- a/ports/stm32/nimble_hci_uart.c +++ b/ports/stm32/nimble_hci_uart.c @@ -26,15 +26,54 @@ #include "py/runtime.h" #include "py/mphal.h" -#include "uart.h" -#include "pendsv.h" #include "extmod/nimble/nimble/hci_uart.h" -#include "drivers/cyw43/cywbt.h" #if MICROPY_BLUETOOTH_NIMBLE +#if defined(STM32WB) + +/******************************************************************************/ +// HCI over IPCC + +#include "rfcore.h" + +int nimble_hci_uart_configure(uint32_t port) { + (void)port; + return 0; +} + +int nimble_hci_uart_set_baudrate(uint32_t baudrate) { + (void)baudrate; + return 0; +} + +int nimble_hci_uart_activate(void) { + rfcore_ble_init(); + return 0; +} + +void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) { + // Protect in case it's called from ble_npl_sem_pend at thread-level + MICROPY_PY_LWIP_ENTER + rfcore_ble_check_msg(rx_cb, rx_arg); + MICROPY_PY_LWIP_EXIT +} + +void nimble_hci_uart_tx_strn(const char *str, uint len) { + MICROPY_PY_LWIP_ENTER + rfcore_ble_hci_cmd(len, (const uint8_t*)str); + MICROPY_PY_LWIP_EXIT +} + +#else + /******************************************************************************/ -// UART +// HCI over UART + +#include "pendsv.h" +#include "uart.h" +#include "drivers/cyw43/cywbt.h" + pyb_uart_obj_t bt_hci_uart_obj; static uint8_t hci_uart_rxbuf[512]; @@ -130,4 +169,6 @@ void nimble_hci_uart_tx_strn(const char *str, uint len) { uart_tx_strn(&bt_hci_uart_obj, str, len); } +#endif // defined(STM32WB) + #endif // MICROPY_BLUETOOTH_NIMBLE diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c new file mode 100644 index 0000000000000..2b45bb2eeb2a1 --- /dev/null +++ b/ports/stm32/rfcore.c @@ -0,0 +1,425 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "py/mperrno.h" +#include "py/mphal.h" +#include "rtc.h" +#include "rfcore.h" + +#if defined(STM32WB) + +// Define to 1 to print traces of HCI packets +#define HCI_TRACE (0) + +#define IPCC_CH_BLE (0x01) // BLE HCI command and response +#define IPCC_CH_SYS (0x02) // system HCI command and response +#define IPCC_CH_MM (0x08) // release buffer +#define IPCC_CH_HCI_ACL (0x20) // HCI ACL outgoing data + +#define OGF_VENDOR (0x3f) +#define OCF_WRITE_CONFIG (0x0c) +#define OCF_SET_TX_POWER (0x0f) +#define OCF_BLE_INIT (0x66) + +#define HCI_OPCODE(ogf, ocf) ((ogf) << 10 | (ocf)) + +typedef struct _tl_list_node_t { + volatile struct _tl_list_node_t *next; + volatile struct _tl_list_node_t *prev; + uint8_t body[0]; +} tl_list_node_t; + +typedef struct _parse_hci_info_t { + int (*cb_fun)(void*, uint8_t); + void *cb_env; + bool was_hci_reset_evt; +} parse_hci_info_t; + +static volatile uint32_t ipcc_mem_dev_info_tab[8]; +static volatile uint32_t ipcc_mem_ble_tab[4]; +static volatile uint32_t ipcc_mem_sys_tab[2]; +static volatile uint32_t ipcc_mem_memmgr_tab[7]; + +static volatile uint32_t ipcc_mem_sys_cmd_buf[272 / 4]; +static volatile tl_list_node_t ipcc_mem_sys_queue; + +static volatile tl_list_node_t ipcc_mem_memmgr_free_buf_queue; +static volatile uint32_t ipcc_mem_memmgr_ble_spare_evt_buf[272 / 4]; +static volatile uint32_t ipcc_mem_memmgr_sys_spare_evt_buf[272 / 4]; +static volatile uint32_t ipcc_mem_memmgr_evt_pool[6 * 272 / 4]; + +static volatile uint32_t ipcc_mem_ble_cmd_buf[272 / 4]; +static volatile uint32_t ipcc_mem_ble_cs_buf[272 / 4]; +static volatile tl_list_node_t ipcc_mem_ble_evt_queue; +static volatile uint32_t ipcc_mem_ble_hci_acl_data_buf[272 / 4]; + +/******************************************************************************/ +// Transport layer linked list + +STATIC void tl_list_init(volatile tl_list_node_t *n) { + n->next = n; + n->prev = n; +} + +STATIC volatile tl_list_node_t *tl_list_unlink(volatile tl_list_node_t *n) { + volatile tl_list_node_t *next = n->next; + volatile tl_list_node_t *prev = n->prev; + prev->next = next; + next->prev = prev; + return next; +} + +STATIC void tl_list_append(volatile tl_list_node_t *head, volatile tl_list_node_t *n) { + n->next = head; + n->prev = head->prev; + head->prev->next = n; + head->prev = n; +} + +/******************************************************************************/ +// IPCC interface + +STATIC uint32_t get_ipccdba(void) { + return *(uint32_t*)(OPTION_BYTE_BASE + 0x68) & 0x3fff; +} + +STATIC volatile void **get_buffer_table(void) { + return (volatile void**)(SRAM2A_BASE + get_ipccdba()); +} + +void ipcc_init(uint32_t irq_pri) { + // Setup buffer table pointers + volatile void **tab = get_buffer_table(); + tab[0] = &ipcc_mem_dev_info_tab[0]; + tab[1] = &ipcc_mem_ble_tab[0]; + tab[3] = &ipcc_mem_sys_tab[0]; + tab[4] = &ipcc_mem_memmgr_tab[0]; + + // Start IPCC peripheral + __HAL_RCC_IPCC_CLK_ENABLE(); + + // Enable wanted IRQs + IPCC->C1CR = 0;//IPCC_C1CR_RXOIE; + IPCC->C1MR = 0xffffffff; + NVIC_SetPriority(IPCC_C1_RX_IRQn, irq_pri); + HAL_NVIC_EnableIRQ(IPCC_C1_RX_IRQn); + + // Device info table will be populated by FUS/WS + + // Populate system table + tl_list_init(&ipcc_mem_sys_queue); + ipcc_mem_sys_tab[0] = (uint32_t)&ipcc_mem_sys_cmd_buf[0]; + ipcc_mem_sys_tab[1] = (uint32_t)&ipcc_mem_sys_queue; + + // Populate memory manager table + tl_list_init(&ipcc_mem_memmgr_free_buf_queue); + ipcc_mem_memmgr_tab[0] = (uint32_t)&ipcc_mem_memmgr_ble_spare_evt_buf[0]; + ipcc_mem_memmgr_tab[1] = (uint32_t)&ipcc_mem_memmgr_sys_spare_evt_buf[0]; + ipcc_mem_memmgr_tab[2] = (uint32_t)&ipcc_mem_memmgr_evt_pool[0]; + ipcc_mem_memmgr_tab[3] = sizeof(ipcc_mem_memmgr_evt_pool); + ipcc_mem_memmgr_tab[4] = (uint32_t)&ipcc_mem_memmgr_free_buf_queue; + ipcc_mem_memmgr_tab[5] = 0; + ipcc_mem_memmgr_tab[6] = 0; + + // Populate BLE table + tl_list_init(&ipcc_mem_ble_evt_queue); + ipcc_mem_ble_tab[0] = (uint32_t)&ipcc_mem_ble_cmd_buf[0]; + ipcc_mem_ble_tab[1] = (uint32_t)&ipcc_mem_ble_cs_buf[0]; + ipcc_mem_ble_tab[2] = (uint32_t)&ipcc_mem_ble_evt_queue; + ipcc_mem_ble_tab[3] = (uint32_t)&ipcc_mem_ble_hci_acl_data_buf[0]; +} + +STATIC int ipcc_wait_ack(unsigned int ch, uint32_t timeout_ms) { + uint32_t t0 = mp_hal_ticks_ms(); + while (IPCC->C1TOC2SR & ch) { + if (mp_hal_ticks_ms() - t0 > timeout_ms) { + printf("ipcc_wait_ack: timeout\n"); + return -MP_ETIMEDOUT; + } + } + // C2 cleared IPCC flag + return 0; +} + +STATIC int ipcc_wait_msg(unsigned int ch, uint32_t timeout_ms) { + uint32_t t0 = mp_hal_ticks_ms(); + while (!(IPCC->C2TOC1SR & ch)) { + if (mp_hal_ticks_ms() - t0 > timeout_ms) { + printf("ipcc_wait_msg: timeout\n"); + return -MP_ETIMEDOUT; + } + } + // C2 set IPCC flag + return 0; +} + +/******************************************************************************/ +// Transport layer HCI interface + +STATIC void tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) { + const char *kind; + size_t len = 3 + buf[2]; + switch (buf[0]) { + case 0x02: { + // Standard BT HCI ACL packet + kind = "HCI_ACL"; + if (parse != NULL) { + for (size_t i = 0; i < len; ++i) { + parse->cb_fun(parse->cb_env, buf[i]); + } + } + break; + } + case 0x04: { + // Standard BT HCI event packet + kind = "HCI_EVT"; + if (parse != NULL) { + bool fix = false; + if (buf[1] == 0x0e && len == 7 && buf[3] == 0x01 && buf[4] == 0x63 && buf[5] == 0x0c && buf[6] == 0x01) { + len -= 1; + fix = true; + } + for (size_t i = 0; i < len; ++i) { + parse->cb_fun(parse->cb_env, buf[i]); + } + if (fix) { + len += 1; + parse->cb_fun(parse->cb_env, 0x00); // success + } + // Check for successful HCI_Reset event + parse->was_hci_reset_evt = buf[1] == 0x0e && buf[2] == 0x04 && buf[3] == 0x01 + && buf[4] == 0x03 && buf[5] == 0x0c && buf[6] == 0x00; + } + break; + } + case 0x11: { + // Response packet + // assert(buf[1] == 0x0e); + kind = "VEND_RESP"; + //uint16_t cmd = buf[4] | buf[5] << 8; + //uint8_t status = buf[6]; + break; + } + case 0x12: { + // Event packet + // assert(buf[1] == 0xff); + kind = "VEND_EVT"; + //uint16_t evt = buf[3] | buf[4] << 8; + break; + } + default: + kind = "HCI_UNKNOWN"; + break; + } + + #if HCI_TRACE + printf("[% 8d] %s(%02x", mp_hal_ticks_ms(), kind, buf[0]); + for (int i = 1; i < len; ++i) { + printf(":%02x", buf[i]); + } + printf(")\n"); + #else + (void)kind; + #endif +} + +STATIC void tl_check_msg(volatile tl_list_node_t *head, unsigned int ch, parse_hci_info_t *parse) { + if (IPCC->C2TOC1SR & ch) { + // Message available on CH2 + volatile tl_list_node_t *cur = head->next; + bool free = false; + while (cur != head) { + tl_parse_hci_msg((uint8_t*)cur->body, parse); + volatile tl_list_node_t *next = tl_list_unlink(cur); + if ((void*)&ipcc_mem_memmgr_evt_pool[0] <= (void*)cur + && (void*)cur < (void*)&ipcc_mem_memmgr_evt_pool[MP_ARRAY_SIZE(ipcc_mem_memmgr_evt_pool)]) { + // Place memory back in free pool + tl_list_append(&ipcc_mem_memmgr_free_buf_queue, cur); + free = true; + } + cur = next; + } + if (free) { + // Notify change in free pool + IPCC->C1SCR = IPCC_CH_MM << 16; + } + // Clear receive channel + IPCC->C1SCR = ch; + } +} + +STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opcode, size_t len, const uint8_t *buf) { + tl_list_node_t *n = (tl_list_node_t*)cmd; + n->next = n; + n->prev = n; + cmd[8] = hdr; + cmd[9] = opcode; + cmd[10] = opcode >> 8; + cmd[11] = len; + memcpy(&cmd[12], buf, len); + // IPCC indicate + IPCC->C1SCR = ch << 16; +} + +STATIC void tl_sys_wait_resp(const uint8_t *buf, unsigned int ch) { + if (ipcc_wait_ack(ch, 250) == 0) { + tl_parse_hci_msg(buf, NULL); + } +} + +STATIC void tl_sys_hci_cmd_resp(uint16_t opcode, size_t len, const uint8_t *buf) { + tl_hci_cmd((uint8_t*)&ipcc_mem_sys_cmd_buf, IPCC_CH_SYS, 0x10, opcode, len, buf); + tl_sys_wait_resp((uint8_t*)&ipcc_mem_sys_cmd_buf, IPCC_CH_SYS); +} + +STATIC void tl_ble_hci_cmd_resp(uint16_t opcode, size_t len, const uint8_t *buf) { + tl_hci_cmd((uint8_t*)&ipcc_mem_ble_cmd_buf[0], IPCC_CH_BLE, 0x01, opcode, len, buf); + ipcc_wait_msg(IPCC_CH_BLE, 250); + tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, NULL); +} + +/******************************************************************************/ +// RF core interface + +void rfcore_init(void) { + // Ensure LSE is running + rtc_init_finalise(); + + // Select LSE as RF wakeup source + RCC->CSR = (RCC->CSR & ~RCC_CSR_RFWKPSEL) | 1 << RCC_CSR_RFWKPSEL_Pos; + + // Initialise IPCC and shared memory structures + ipcc_init(IRQ_PRI_SDIO); + + // Boot the second core + __SEV(); + __WFE(); + PWR->CR4 |= PWR_CR4_C2BOOT; +} + +static const struct { + uint8_t* pBleBufferAddress; // unused + uint32_t BleBufferSize; // unused + uint16_t NumAttrRecord; + uint16_t NumAttrServ; + uint16_t AttrValueArrSize; + uint8_t NumOfLinks; + uint8_t ExtendedPacketLengthEnable; + uint8_t PrWriteListSize; + uint8_t MblockCount; + uint16_t AttMtu; + uint16_t SlaveSca; + uint8_t MasterSca; + uint8_t LsSource; // 0=LSE 1=internal RO + uint32_t MaxConnEventLength; + uint16_t HsStartupTime; + uint8_t ViterbiEnable; + uint8_t LlOnly; // 0=LL+Host, 1=LL only + uint8_t HwVersion; +} ble_init_params = { + 0, + 0, + 0, // NumAttrRecord + 0, // NumAttrServ + 0, // AttrValueArrSize + 1, // NumOfLinks + 1, // ExtendedPacketLengthEnable + 0, // PrWriteListSize + 0x79, // MblockCount + 0, // AttMtu + 0, // SlaveSca + 0, // MasterSca + 1, // LsSource + 0xffffffff, // MaxConnEventLength + 0x148, // HsStartupTime + 0, // ViterbiEnable + 1, // LlOnly + 0, // HwVersion +}; + +void rfcore_ble_init(void) { + // Clear any outstanding messages from ipcc_init + tl_check_msg(&ipcc_mem_sys_queue, IPCC_CH_SYS, NULL); + tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, NULL); + + // Configure and reset the BLE controller + tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), sizeof(ble_init_params), (const uint8_t*)&ble_init_params); + tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), 0, NULL); +} + +void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) { + #if HCI_TRACE + printf("[% 8d] HCI_CMD(%02x", mp_hal_ticks_ms(), src[0]); + for (int i = 1; i < len; ++i) { + printf(":%02x", src[i]); + } + printf(")\n"); + #endif + + tl_list_node_t *n; + uint32_t ch; + if (src[0] == 0x01) { + n = (tl_list_node_t*)&ipcc_mem_ble_cmd_buf[0]; + ch = IPCC_CH_BLE; + } else if (src[0] == 0x02) { + n = (tl_list_node_t*)&ipcc_mem_ble_hci_acl_data_buf[0]; + ch = IPCC_CH_HCI_ACL; + } else { + printf("** UNEXPECTED HCI HDR: 0x%02x **\n", src[0]); + return; + } + + n->next = n; + n->prev = n; + memcpy(n->body, src, len); + + // IPCC indicate + IPCC->C1SCR = ch << 16; +} + +void rfcore_ble_check_msg(int (*cb)(void*, uint8_t), void *env) { + parse_hci_info_t parse = { cb, env, false }; + tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, &parse); + + // Intercept HCI_Reset events and reconfigure the controller following the reset + if (parse.was_hci_reset_evt) { + uint8_t buf[8]; + buf[0] = 0; // config offset + buf[1] = 6; // config length + mp_hal_get_mac(MP_HAL_MAC_BDADDR, &buf[2]); + #define SWAP_UINT8(a, b) { uint8_t temp = a; a = b; b = temp; } + SWAP_UINT8(buf[2], buf[7]); + SWAP_UINT8(buf[3], buf[6]); + SWAP_UINT8(buf[4], buf[5]); + tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_WRITE_CONFIG), 8, buf); // set BDADDR + tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_SET_TX_POWER), 2, (const uint8_t*)"\x00\x06"); // 0 dBm + } +} + +#endif // defined(STM32WB) diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h new file mode 100644 index 0000000000000..ef12707b7ddf4 --- /dev/null +++ b/ports/stm32/rfcore.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32_RFCORE_H +#define MICROPY_INCLUDED_STM32_RFCORE_H + +#include + +void rfcore_init(void); + +void rfcore_ble_init(void); +void rfcore_ble_hci_cmd(size_t len, const uint8_t *src); +void rfcore_ble_check_msg(int (*cb)(void*, uint8_t), void *env); + +#endif // MICROPY_INCLUDED_STM32_RFCORE_H From 32eae53fbc94a1d91fe67025aeef05ad3e20b187 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Nov 2019 14:56:48 +1100 Subject: [PATCH 0673/1299] stm32/boards: Enable support for bluetooth on WB55 boards. --- ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h | 4 ++++ ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk | 4 ++++ ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h | 4 ++++ ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h index beca2165696ab..54747cb04de13 100644 --- a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h @@ -61,3 +61,7 @@ #define MICROPY_HW_USB_FS (1) #define USBD_CDC_RX_DATA_SIZE (512) #define USBD_CDC_TX_DATA_SIZE (512) + +// Bluetooth config +#define MICROPY_HW_BLE_UART_ID (0) +#define MICROPY_HW_BLE_UART_BAUDRATE (115200) diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk index b0f93c006f2ec..cd9f104ef5328 100644 --- a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk @@ -3,3 +3,7 @@ CMSIS_MCU = STM32WB55xx AF_FILE = boards/stm32wb55_af.csv LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.o + +# MicroPython settings +MICROPY_PY_BLUETOOTH = 1 +MICROPY_BLUETOOTH_NIMBLE = 1 diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h index eebf30f628d21..eeedfb0844143 100644 --- a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h @@ -40,3 +40,7 @@ #define MICROPY_HW_USB_FS (1) #define USBD_CDC_RX_DATA_SIZE (512) #define USBD_CDC_TX_DATA_SIZE (512) + +// Bluetooth config +#define MICROPY_HW_BLE_UART_ID (0) +#define MICROPY_HW_BLE_UART_BAUDRATE (115200) diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk index b0f93c006f2ec..cd9f104ef5328 100644 --- a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk @@ -3,3 +3,7 @@ CMSIS_MCU = STM32WB55xx AF_FILE = boards/stm32wb55_af.csv LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb55xx_cm4.o + +# MicroPython settings +MICROPY_PY_BLUETOOTH = 1 +MICROPY_BLUETOOTH_NIMBLE = 1 From 2ee9e1a4edf31824f2ff4ba6fb73129c798dcb36 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Nov 2019 17:25:40 +1100 Subject: [PATCH 0674/1299] extmod/modbtree: Make FILEVTABLE const to put it in ROM. --- extmod/modbtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/modbtree.c b/extmod/modbtree.c index a2bff06d447bd..2a08a9cab04bd 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -320,7 +320,7 @@ STATIC const mp_obj_type_t btree_type = { .locals_dict = (void*)&btree_locals_dict, }; -STATIC FILEVTABLE btree_stream_fvtable = { +STATIC const FILEVTABLE btree_stream_fvtable = { mp_stream_posix_read, mp_stream_posix_write, mp_stream_posix_lseek, From f2ecfe8b83b4efe24d721778e324a31237653627 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Nov 2019 17:26:10 +1100 Subject: [PATCH 0675/1299] py/nativeglue: Remove unused mp_obj_new_cell from mp_fun_table. It has been unused since 9988618e0e0f5c319e31b135d993e22efb593093 --- py/emitnx86.c | 1 - py/nativeglue.c | 1 - py/runtime0.h | 1 - 3 files changed, 3 deletions(-) diff --git a/py/emitnx86.c b/py/emitnx86.c index 7c96c3b82b352..0122e46bab5ee 100644 --- a/py/emitnx86.c +++ b/py/emitnx86.c @@ -60,7 +60,6 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_UNPACK_EX] = 3, [MP_F_DELETE_NAME] = 1, [MP_F_DELETE_GLOBAL] = 1, - [MP_F_NEW_CELL] = 1, [MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3, [MP_F_ARG_CHECK_NUM_SIG] = 3, [MP_F_SETUP_CODE_STATE] = 4, diff --git a/py/nativeglue.c b/py/nativeglue.c index 4405b2d116be4..08fbd3c309f3b 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -259,7 +259,6 @@ const void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_unpack_ex, mp_delete_name, mp_delete_global, - mp_obj_new_cell, mp_make_closure_from_raw_code, mp_arg_check_num_sig, mp_setup_code_state, diff --git a/py/runtime0.h b/py/runtime0.h index 364f237f66a6f..f588110c0d7a4 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -196,7 +196,6 @@ typedef enum { MP_F_UNPACK_EX, MP_F_DELETE_NAME, MP_F_DELETE_GLOBAL, - MP_F_NEW_CELL, MP_F_MAKE_CLOSURE_FROM_RAW_CODE, MP_F_ARG_CHECK_NUM_SIG, MP_F_SETUP_CODE_STATE, From 36c9be6f60314684edf131f554efec7120e20f30 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 4 Nov 2019 15:31:42 +1100 Subject: [PATCH 0676/1299] tools/mpy-tool.py: Use "@progbits #" attribute for native xtensa code. --- tools/mpy-tool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 39362bc092652..9b0b8e8cd2bf2 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -422,7 +422,8 @@ def __init__(self, code_kind, fun_data, prelude_offset, prelude, qstr_links, qst self.prelude = prelude self.qstr_links = qstr_links self.type_sig = type_sig - if config.native_arch in (MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64): + if config.native_arch in (MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64, + MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN): self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",@progbits # ")))' else: self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",%progbits @ ")))' From 742030945c779c57c30c62c7b1353758d29dc228 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 4 Nov 2019 15:32:20 +1100 Subject: [PATCH 0677/1299] esp32/Makefile: Add correct arch to MPY_CROSS_FLAGS for native code. --- ports/esp32/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 37261d17bd2e4..42b01a4e605bc 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -275,6 +275,9 @@ COPT += -Os -DNDEBUG #LDFLAGS += --gc-sections endif +# Options for mpy-cross +MPY_CROSS_FLAGS += -march=xtensawin + # Enable SPIRAM support if CONFIG_ESP32_SPIRAM_SUPPORT=y in sdkconfig ifeq ($(CONFIG_ESP32_SPIRAM_SUPPORT),y) CFLAGS_COMMON += -mfix-esp32-psram-cache-issue From 576ed8922472f41dd603da9bd719bd9f1adbf31e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 29 Oct 2019 17:28:11 +1100 Subject: [PATCH 0678/1299] py/objgenerator: Remove globals from mp_obj_gen_instance_t. This wasn't necessary as the wrapped function already has a reference to its globals. But it had a dual purpose of tracking whether the function was currently running, so replace it with a bool. --- py/objgenerator.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/py/objgenerator.c b/py/objgenerator.c index 2cfdb12f63853..1850377cb9516 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -43,7 +43,7 @@ const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, typedef struct _mp_obj_gen_instance_t { mp_obj_base_t base; - mp_obj_dict_t *globals; + bool is_running; mp_code_state_t code_state; } mp_obj_gen_instance_t; @@ -60,7 +60,7 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t)); o->base.type = &mp_type_gen_instance; - o->globals = self_fun->globals; + o->is_running = false; o->code_state.fun_bc = self_fun; o->code_state.ip = 0; o->code_state.n_state = n_state; @@ -105,7 +105,7 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k o->base.type = &mp_type_gen_instance; // Parse the input arguments and set up the code state - o->globals = self_fun->globals; + o->is_running = false; o->code_state.fun_bc = self_fun; o->code_state.ip = (const byte*)prelude_offset; o->code_state.n_state = n_state; @@ -168,16 +168,15 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ } } - // We set self->globals=NULL while executing, for a sentinel to ensure the generator - // cannot be reentered during execution - if (self->globals == NULL) { + // Ensure the generator cannot be reentered during execution + if (self->is_running) { mp_raise_ValueError("generator already executing"); } + self->is_running = true; // Set up the correct globals context for the generator and execute it self->code_state.old_globals = mp_globals_get(); - mp_globals_set(self->globals); - self->globals = NULL; + mp_globals_set(self->code_state.fun_bc->globals); mp_vm_return_kind_t ret_kind; @@ -194,9 +193,10 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ ret_kind = mp_execute_bytecode(&self->code_state, throw_value); } - self->globals = mp_globals_get(); mp_globals_set(self->code_state.old_globals); + self->is_running = false; + switch (ret_kind) { case MP_VM_RETURN_NORMAL: default: From 5578182ec97509dcc37521b78da5ee31b96f6b4e Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 29 Oct 2019 21:04:55 +1100 Subject: [PATCH 0679/1299] py/objgenerator: Allow pend_throw to an unstarted generator. Replace the is_running field with a tri-state variable to indicate running/not-running/pending-exception. Update tests to cover the various cases. This allows cancellation in uasyncio even if the coroutine hasn't been executed yet. Fixes #5242 --- py/objgenerator.c | 52 +++++++++------- tests/basics/generator_pend_throw.py | 76 +++++++++++++++++++++++- tests/basics/generator_pend_throw.py.exp | 12 +++- 3 files changed, 113 insertions(+), 27 deletions(-) diff --git a/py/objgenerator.c b/py/objgenerator.c index 1850377cb9516..903a6469cccd4 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -43,7 +43,10 @@ const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, typedef struct _mp_obj_gen_instance_t { mp_obj_base_t base; - bool is_running; + // mp_const_none: Not-running, no exception. + // MP_OBJ_NULL: Running, no exception. + // other: Not running, pending exception. + mp_obj_t pend_exc; mp_code_state_t code_state; } mp_obj_gen_instance_t; @@ -60,7 +63,7 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t)); o->base.type = &mp_type_gen_instance; - o->is_running = false; + o->pend_exc = mp_const_none; o->code_state.fun_bc = self_fun; o->code_state.ip = 0; o->code_state.n_state = n_state; @@ -105,7 +108,7 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k o->base.type = &mp_type_gen_instance; // Parse the input arguments and set up the code state - o->is_running = false; + o->pend_exc = mp_const_none; o->code_state.fun_bc = self_fun; o->code_state.ip = (const byte*)prelude_offset; o->code_state.n_state = n_state; @@ -151,28 +154,30 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ *ret_val = MP_OBJ_STOP_ITERATION; return MP_VM_RETURN_NORMAL; } + + // Ensure the generator cannot be reentered during execution + if (self->pend_exc == MP_OBJ_NULL) { + mp_raise_ValueError("generator already executing"); + } + + #if MICROPY_PY_GENERATOR_PEND_THROW + // If exception is pending (set using .pend_throw()), process it now. + if (self->pend_exc != mp_const_none) { + throw_value = self->pend_exc; + } + #endif + + // If the generator is started, allow sending a value. if (self->code_state.sp == self->code_state.state - 1) { if (send_value != mp_const_none) { mp_raise_TypeError("can't send non-None value to a just-started generator"); } } else { - #if MICROPY_PY_GENERATOR_PEND_THROW - // If exception is pending (set using .pend_throw()), process it now. - if (*self->code_state.sp != mp_const_none) { - throw_value = *self->code_state.sp; - *self->code_state.sp = MP_OBJ_NULL; - } else - #endif - { - *self->code_state.sp = send_value; - } + *self->code_state.sp = send_value; } - // Ensure the generator cannot be reentered during execution - if (self->is_running) { - mp_raise_ValueError("generator already executing"); - } - self->is_running = true; + // Mark as running + self->pend_exc = MP_OBJ_NULL; // Set up the correct globals context for the generator and execute it self->code_state.old_globals = mp_globals_get(); @@ -195,7 +200,8 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ mp_globals_set(self->code_state.old_globals); - self->is_running = false; + // Mark as not running + self->pend_exc = mp_const_none; switch (ret_kind) { case MP_VM_RETURN_NORMAL: @@ -313,11 +319,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close); #if MICROPY_PY_GENERATOR_PEND_THROW STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); - if (self->code_state.sp == self->code_state.state - 1) { - mp_raise_TypeError("can't pend throw to just-started generator"); + if (self->pend_exc == MP_OBJ_NULL) { + mp_raise_ValueError("generator already executing"); } - mp_obj_t prev = *self->code_state.sp; - *self->code_state.sp = exc_in; + mp_obj_t prev = self->pend_exc; + self->pend_exc = exc_in; return prev; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_pend_throw_obj, gen_instance_pend_throw); diff --git a/tests/basics/generator_pend_throw.py b/tests/basics/generator_pend_throw.py index f00ff793b64fa..ae8c21189e9e0 100644 --- a/tests/basics/generator_pend_throw.py +++ b/tests/basics/generator_pend_throw.py @@ -13,6 +13,7 @@ def gen(): raise SystemExit +# Verify that an injected exception will be raised from next(). print(next(g)) print(next(g)) g.pend_throw(ValueError()) @@ -25,7 +26,76 @@ def gen(): print("ret was:", v) + +# Verify that pend_throw works on an unstarted coroutine. +g = gen() +g.pend_throw(OSError()) +try: + next(g) +except Exception as e: + print("raised", repr(e)) + + +# Verify that you can't resume the coroutine from within the running coroutine. +def gen_next(): + next(g) + yield 1 + +g = gen_next() + +try: + next(g) +except Exception as e: + print("raised", repr(e)) + + +# Verify that you can't pend_throw from within the running coroutine. +def gen_pend_throw(): + g.pend_throw(ValueError()) + yield 1 + +g = gen_pend_throw() + +try: + next(g) +except Exception as e: + print("raised", repr(e)) + + +# Verify that the pend_throw exception can be ignored. +class CancelledError(Exception): + pass + +def gen_cancelled(): + for i in range(5): + try: + yield i + except CancelledError: + print('ignore CancelledError') + +g = gen_cancelled() +print(next(g)) +g.pend_throw(CancelledError()) +print(next(g)) +# ...but not if the generator hasn't started. +g = gen_cancelled() +g.pend_throw(CancelledError()) try: - gen().pend_throw(ValueError()) -except TypeError: - print("TypeError") + next(g) +except Exception as e: + print("raised", repr(e)) + + +# Verify that calling pend_throw returns the previous exception. +g = gen() +next(g) +print(repr(g.pend_throw(CancelledError()))) +print(repr(g.pend_throw(OSError))) + + +# Verify that you can pend_throw(None) to cancel a previous pend_throw. +g = gen() +next(g) +g.pend_throw(CancelledError()) +print(repr(g.pend_throw(None))) +print(next(g)) diff --git a/tests/basics/generator_pend_throw.py.exp b/tests/basics/generator_pend_throw.py.exp index ed4d8829580ad..8a3dadfec7a38 100644 --- a/tests/basics/generator_pend_throw.py.exp +++ b/tests/basics/generator_pend_throw.py.exp @@ -2,4 +2,14 @@ 1 raised ValueError() ret was: None -TypeError +raised OSError() +raised ValueError('generator already executing',) +raised ValueError('generator already executing',) +0 +ignore CancelledError +1 +raised CancelledError() +None +CancelledError() +CancelledError() +1 From f4601af10a4e1f1a588596ed1bb76cb7578ab726 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 1 Nov 2019 21:04:07 +1100 Subject: [PATCH 0680/1299] py/persistentcode: Move declarations for .mpy header from .c to .h file. --- py/persistentcode.c | 37 ------------------------------------- py/persistentcode.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index d55e3715925f8..84385c1713fef 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -40,43 +40,6 @@ #define QSTR_LAST_STATIC MP_QSTR_zip -// Macros to encode/decode flags to/from the feature byte -#define MPY_FEATURE_ENCODE_FLAGS(flags) (flags) -#define MPY_FEATURE_DECODE_FLAGS(feat) ((feat) & 3) - -// Macros to encode/decode native architecture to/from the feature byte -#define MPY_FEATURE_ENCODE_ARCH(arch) ((arch) << 2) -#define MPY_FEATURE_DECODE_ARCH(feat) ((feat) >> 2) - -// The feature flag bits encode the compile-time config options that -// affect the generate bytecode. -#define MPY_FEATURE_FLAGS ( \ - ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) << 0) \ - | ((MICROPY_PY_BUILTINS_STR_UNICODE) << 1) \ - ) -// This is a version of the flags that can be configured at runtime. -#define MPY_FEATURE_FLAGS_DYNAMIC ( \ - ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) << 0) \ - | ((MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) << 1) \ - ) - -// Define the host architecture -#if MICROPY_EMIT_X86 -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X86) -#elif MICROPY_EMIT_X64 -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X64) -#elif MICROPY_EMIT_THUMB -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7M) -#elif MICROPY_EMIT_ARM -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV6) -#elif MICROPY_EMIT_XTENSA -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSA) -#elif MICROPY_EMIT_XTENSAWIN -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSAWIN) -#else -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) -#endif - #if MICROPY_DYNAMIC_COMPILER #define MPY_FEATURE_ARCH_DYNAMIC mp_dynamic_compiler.native_arch #else diff --git a/py/persistentcode.h b/py/persistentcode.h index aba44ea2db1cb..a6978c2a33100 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -33,6 +33,43 @@ // The current version of .mpy files #define MPY_VERSION 5 +// Macros to encode/decode flags to/from the feature byte +#define MPY_FEATURE_ENCODE_FLAGS(flags) (flags) +#define MPY_FEATURE_DECODE_FLAGS(feat) ((feat) & 3) + +// Macros to encode/decode native architecture to/from the feature byte +#define MPY_FEATURE_ENCODE_ARCH(arch) ((arch) << 2) +#define MPY_FEATURE_DECODE_ARCH(feat) ((feat) >> 2) + +// The feature flag bits encode the compile-time config options that +// affect the generate bytecode. +#define MPY_FEATURE_FLAGS ( \ + ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) << 0) \ + | ((MICROPY_PY_BUILTINS_STR_UNICODE) << 1) \ + ) +// This is a version of the flags that can be configured at runtime. +#define MPY_FEATURE_FLAGS_DYNAMIC ( \ + ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) << 0) \ + | ((MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) << 1) \ + ) + +// Define the host architecture +#if MICROPY_EMIT_X86 +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X86) +#elif MICROPY_EMIT_X64 +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X64) +#elif MICROPY_EMIT_THUMB +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7M) +#elif MICROPY_EMIT_ARM +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV6) +#elif MICROPY_EMIT_XTENSA +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSA) +#elif MICROPY_EMIT_XTENSAWIN +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSAWIN) +#else +#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) +#endif + enum { MP_NATIVE_ARCH_NONE = 0, MP_NATIVE_ARCH_X86, From 80df377e9512ac839ab19192ff1897ba30be098b Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 30 Oct 2019 16:26:11 +1100 Subject: [PATCH 0681/1299] py/modsys: Report .mpy version in sys.implementation. This commit adds a sys.implementation.mpy entry when the system supports importing .mpy files. This entry is a 16-bit integer which encodes two bytes of information from the header of .mpy files that are supported by the system being run: the second and third bytes, .mpy version, and flags and native architecture. This allows determining the supported .mpy file dynamically by code, and also for the user to find it out by inspecting this value. It's further possible to dynamically detect if the system supports importing .mpy files by `hasattr(sys.implementation, 'mpy')`. --- py/modsys.c | 29 ++++++++++++++++++++++------- py/persistentcode.h | 4 ++++ tests/basics/sys1.py | 6 ++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/py/modsys.c b/py/modsys.c index 4886419d0edb6..29fac7c319340 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -34,6 +34,7 @@ #include "py/stream.h" #include "py/smallint.h" #include "py/runtime.h" +#include "py/persistentcode.h" #if MICROPY_PY_SYS_SETTRACE #include "py/objmodule.h" @@ -66,22 +67,36 @@ STATIC const mp_obj_tuple_t mp_sys_implementation_version_info_obj = { 3, { I(MICROPY_VERSION_MAJOR), I(MICROPY_VERSION_MINOR), I(MICROPY_VERSION_MICRO) } }; +#if MICROPY_PERSISTENT_CODE_LOAD +#define SYS_IMPLEMENTATION_ELEMS \ + MP_ROM_QSTR(MP_QSTR_micropython), \ + MP_ROM_PTR(&mp_sys_implementation_version_info_obj), \ + MP_ROM_INT(MPY_FILE_HEADER_INT) +#else +#define SYS_IMPLEMENTATION_ELEMS \ + MP_ROM_QSTR(MP_QSTR_micropython), \ + MP_ROM_PTR(&mp_sys_implementation_version_info_obj) +#endif #if MICROPY_PY_ATTRTUPLE -STATIC const qstr impl_fields[] = { MP_QSTR_name, MP_QSTR_version }; +STATIC const qstr impl_fields[] = { + MP_QSTR_name, + MP_QSTR_version, + #if MICROPY_PERSISTENT_CODE_LOAD + MP_QSTR_mpy, + #endif +}; STATIC MP_DEFINE_ATTRTUPLE( mp_sys_implementation_obj, impl_fields, - 2, - MP_ROM_QSTR(MP_QSTR_micropython), - MP_ROM_PTR(&mp_sys_implementation_version_info_obj) + 2 + MICROPY_PERSISTENT_CODE_LOAD, + SYS_IMPLEMENTATION_ELEMS ); #else STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { {&mp_type_tuple}, - 2, + 2 + MICROPY_PERSISTENT_CODE_LOAD, { - MP_ROM_QSTR(MP_QSTR_micropython), - MP_ROM_PTR(&mp_sys_implementation_version_info_obj), + SYS_IMPLEMENTATION_ELEMS } }; #endif diff --git a/py/persistentcode.h b/py/persistentcode.h index a6978c2a33100..07e018f8a6248 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -70,6 +70,10 @@ #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) #endif +// 16-bit little-endian integer with the second and third bytes of supported .mpy files +#define MPY_FILE_HEADER_INT (MPY_VERSION \ + | (MPY_FEATURE_ENCODE_FLAGS(MPY_FEATURE_FLAGS) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) + enum { MP_NATIVE_ARCH_NONE = 0, MP_NATIVE_ARCH_X86, diff --git a/tests/basics/sys1.py b/tests/basics/sys1.py index ab913802469b7..095824afaf1fc 100644 --- a/tests/basics/sys1.py +++ b/tests/basics/sys1.py @@ -18,3 +18,9 @@ except AttributeError: # Effectively skip subtests print(True) + +if hasattr(sys.implementation, 'mpy'): + print(type(sys.implementation.mpy)) +else: + # Effectively skip subtests + print(int) From c13f9f209d7a343fe306a24a04eb934ce905b631 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Nov 2019 11:33:03 +1100 Subject: [PATCH 0682/1299] all: Convert nlr_raise(mp_obj_new_exception_msg(x)) to mp_raise_msg(x). This helper function was added a while ago and these are the remaining cases to convert, to save a bit of code size. --- extmod/moductypes.c | 2 +- extmod/moduheapq.c | 2 +- extmod/modutimeq.c | 4 ++-- extmod/network_cyw43.c | 2 +- extmod/vfs_posix_file.c | 2 +- ports/esp32/modesp32.c | 6 +++--- ports/esp32/modmachine.c | 2 +- ports/esp32/modnetwork.c | 4 ++-- ports/esp32/mpthreadport.c | 3 ++- ports/esp8266/esp_mphal.c | 3 +-- ports/esp8266/machine_pin.c | 2 +- ports/esp8266/modesp.c | 2 +- ports/esp8266/modnetwork.c | 8 +++----- ports/nrf/boards/microbit/modules/microbitimage.c | 13 +++++-------- ports/stm32/modnetwork.c | 2 +- ports/stm32/modnwcc3k.c | 2 +- ports/stm32/modusocket.c | 2 +- ports/stm32/mpthreadport.c | 2 +- py/objint.c | 2 +- 19 files changed, 30 insertions(+), 35 deletions(-) diff --git a/extmod/moductypes.c b/extmod/moductypes.c index cf83f43e33b93..62bbcbac224f4 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -558,7 +558,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS); arr_sz &= VALUE_MASK(VAL_TYPE_BITS); if (index >= arr_sz) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "struct: index out of range")); + mp_raise_msg(&mp_type_IndexError, "struct: index out of range"); } if (t->len == 2) { diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c index 1574eb8627a77..f633052105357 100644 --- a/extmod/moduheapq.c +++ b/extmod/moduheapq.c @@ -81,7 +81,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush); STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) { mp_obj_list_t *heap = uheapq_get_heap(heap_in); if (heap->len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); + mp_raise_msg(&mp_type_IndexError, "empty heap"); } mp_obj_t item = heap->items[0]; heap->len -= 1; diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c index 28a2a70c5ec79..0183a0f4b45e5 100644 --- a/extmod/modutimeq.c +++ b/extmod/modutimeq.c @@ -142,7 +142,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_heappush_obj, 4, 4, mod_ut STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) { mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); + mp_raise_msg(&mp_type_IndexError, "empty heap"); } mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref); if (!mp_obj_is_type(list_ref, &mp_type_list) || ret->len < 3) { @@ -167,7 +167,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop); STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) { mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in); if (heap->len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); + mp_raise_msg(&mp_type_IndexError, "empty heap"); } struct qentry *item = &heap->items[0]; diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index fe73b07153ebb..45bb6163e77c8 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -196,7 +196,7 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m int scan_res = cyw43_wifi_scan(self->cyw, &opts, MP_OBJ_TO_PTR(res), network_cyw43_scan_cb); if (scan_res < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "STA must be active")); + mp_raise_msg(&mp_type_OSError, "STA must be active"); } // Wait for scan to finish, with a 10s timeout diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 6f7ce814f3a42..30fde818ebc93 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -44,7 +44,7 @@ typedef struct _mp_obj_vfs_posix_file_t { #ifdef MICROPY_CPYTHON_COMPAT STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { if (o->fd < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "I/O operation on closed file")); + mp_raise_msg(&mp_type_ValueError, "I/O operation on closed file"); } } #else diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c index ada88116760f1..ddc030e3fb6ae 100644 --- a/ports/esp32/modesp32.c +++ b/ports/esp32/modesp32.c @@ -48,7 +48,7 @@ STATIC mp_obj_t esp32_wake_on_touch(const mp_obj_t wake) { if (machine_rtc_config.ext0_pin != -1) { mp_raise_ValueError("no resources"); } - //nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "touchpad wakeup not available for this version of ESP-IDF")); + //mp_raise_msg(&mp_type_RuntimeError, "touchpad wakeup not available for this version of ESP-IDF"); machine_rtc_config.wake_on_touch = mp_obj_is_true(wake); return mp_const_none; @@ -74,7 +74,7 @@ STATIC mp_obj_t esp32_wake_on_ext0(size_t n_args, const mp_obj_t *pos_args, mp_m gpio_num_t pin_id = machine_pin_get_id(args[ARG_pin].u_obj); if (pin_id != machine_rtc_config.ext0_pin) { if (!RTC_IS_VALID_EXT_PIN(pin_id)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); + mp_raise_msg(&mp_type_ValueError, "invalid pin"); } machine_rtc_config.ext0_pin = pin_id; } @@ -109,7 +109,7 @@ STATIC mp_obj_t esp32_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_m gpio_num_t pin_id = machine_pin_get_id(elem[i]); if (!RTC_IS_VALID_EXT_PIN(pin_id)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); + mp_raise_msg(&mp_type_ValueError, "invalid pin"); break; } ext1_pins |= (1ll << pin_id); diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 0c803d0960d18..e722ed2c5b2fa 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -119,7 +119,7 @@ STATIC mp_obj_t machine_sleep_helper(wake_type_t wake_type, size_t n_args, const if (machine_rtc_config.wake_on_touch) { if (esp_sleep_enable_touchpad_wakeup() != ESP_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "esp_sleep_enable_touchpad_wakeup() failed")); + mp_raise_msg(&mp_type_RuntimeError, "esp_sleep_enable_touchpad_wakeup() failed"); } } diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index 012dc5bce8b1e..ba967b8cbd081 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -233,7 +233,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) { /*void error_check(bool status, const char *msg) { if (!status) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg)); + mp_raise_msg(&mp_type_OSError, msg); } } */ @@ -441,7 +441,7 @@ STATIC mp_obj_t esp_scan(mp_obj_t self_in) { wifi_mode_t mode; ESP_EXCEPTIONS(esp_wifi_get_mode(&mode)); if ((mode & WIFI_MODE_STA) == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "STA must be active")); + mp_raise_msg(&mp_type_OSError, "STA must be active"); } mp_obj_t list = mp_obj_new_list(0, NULL); diff --git a/ports/esp32/mpthreadport.c b/ports/esp32/mpthreadport.c index 1c0d889e98808..d7db0ff615226 100644 --- a/ports/esp32/mpthreadport.c +++ b/ports/esp32/mpthreadport.c @@ -27,6 +27,7 @@ #include "stdio.h" +#include "py/runtime.h" #include "py/gc.h" #include "py/mpthread.h" #include "py/mphal.h" @@ -135,7 +136,7 @@ void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, i BaseType_t result = xTaskCreatePinnedToCore(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, &th->id, MP_TASK_COREID); if (result != pdPASS) { mp_thread_mutex_unlock(&thread_mutex); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); + mp_raise_msg(&mp_type_OSError, "can't create thread"); } // adjust the stack_size to provide room to recover from hitting the limit diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c index 2ce288ea3f0fb..25201425b3201 100644 --- a/ports/esp8266/esp_mphal.c +++ b/ports/esp8266/esp_mphal.c @@ -149,8 +149,7 @@ void ets_event_poll(void) { void __assert_func(const char *file, int line, const char *func, const char *expr) { printf("assert:%s:%d:%s: %s\n", file, line, func, expr); - nlr_raise(mp_obj_new_exception_msg(&mp_type_AssertionError, - "C-level assert")); + mp_raise_msg(&mp_type_AssertionError, "C-level assert"); } void mp_hal_signal_input(void) { diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index 14505c8f024c0..1200aa9decdaf 100644 --- a/ports/esp8266/machine_pin.c +++ b/ports/esp8266/machine_pin.c @@ -384,7 +384,7 @@ STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (self->phys_port >= 16) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "pin does not have IRQ capabilities")); + mp_raise_msg(&mp_type_OSError, "pin does not have IRQ capabilities"); } if (n_args > 1 || kw_args->used != 0) { diff --git a/ports/esp8266/modesp.c b/ports/esp8266/modesp.c index 6c9fa9e1316d1..2aeb3d690a0b5 100644 --- a/ports/esp8266/modesp.c +++ b/ports/esp8266/modesp.c @@ -43,7 +43,7 @@ void error_check(bool status, const char *msg) { if (!status) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg)); + mp_raise_msg(&mp_type_OSError, msg); } } diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c index c58aae1cbd005..6bdbe6e23e7ea 100644 --- a/ports/esp8266/modnetwork.c +++ b/ports/esp8266/modnetwork.c @@ -229,8 +229,7 @@ STATIC void esp_scan_cb(void *result, STATUS status) { STATIC mp_obj_t esp_scan(mp_obj_t self_in) { require_if(self_in, STATION_IF); if ((wifi_get_opmode() & STATION_MODE) == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, - "STA must be active")); + mp_raise_msg(&mp_type_OSError, "STA must be active"); } mp_obj_t list = mp_obj_new_list(0, NULL); esp_scan_list = &list; @@ -247,7 +246,7 @@ STATIC mp_obj_t esp_scan(mp_obj_t self_in) { ets_loop_iter(); } if (list == MP_OBJ_NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "scan failed")); + mp_raise_msg(&mp_type_OSError, "scan failed"); } return list; } @@ -313,8 +312,7 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { wifi_softap_dhcps_stop(); } if (!wifi_set_ip_info(self->if_id, &info)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, - "wifi_set_ip_info() failed")); + mp_raise_msg(&mp_type_OSError, "wifi_set_ip_info() failed"); } dns_setserver(0, &dns_addr); if (restart_dhcp_server) { diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c index fca5075089f98..ce4a959f08635 100644 --- a/ports/nrf/boards/microbit/modules/microbitimage.c +++ b/ports/nrf/boards/microbit/modules/microbitimage.c @@ -227,8 +227,7 @@ STATIC mp_obj_t microbit_image_make_new(const mp_obj_type_t *type_in, mp_uint_t return image_from_parsed_str(str, len); } } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "Image(s) takes a string.")); + mp_raise_msg(&mp_type_TypeError, "Image(s) takes a string."); } } @@ -259,8 +258,7 @@ STATIC mp_obj_t microbit_image_make_new(const mp_obj_type_t *type_in, mp_uint_t } default: { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "Image() takes 0 to 3 arguments")); + mp_raise_msg(&mp_type_TypeError, "Image() takes 0 to 3 arguments"); } } } @@ -365,7 +363,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(microbit_image_get_pixel_obj, microbit_image_get_pixel /* Raise an exception if not mutable */ static void check_mutability(microbit_image_obj_t *self) { if (self->base.five) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "image cannot be modified (try copying first)")); + mp_raise_msg(&mp_type_TypeError, "image cannot be modified (try copying first)"); } } @@ -408,11 +406,10 @@ mp_obj_t microbit_image_blit(mp_uint_t n_args, const mp_obj_t *args) { mp_obj_t src = args[1]; if (mp_obj_get_type(src) != µbit_image_type) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "expecting an image")); + mp_raise_msg(&mp_type_TypeError, "expecting an image"); } if (n_args == 7) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "must specify both offsets")); + mp_raise_msg(&mp_type_TypeError, "must specify both offsets"); } mp_int_t x = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[3]); diff --git a/ports/stm32/modnetwork.c b/ports/stm32/modnetwork.c index 19a60103f8f19..4b0f77f9af9a1 100644 --- a/ports/stm32/modnetwork.c +++ b/ports/stm32/modnetwork.c @@ -119,7 +119,7 @@ mp_obj_t mod_network_find_nic(const uint8_t *ip) { return nic; } - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); + mp_raise_msg(&mp_type_OSError, "no available NIC"); } STATIC mp_obj_t network_route(void) { diff --git a/ports/stm32/modnwcc3k.c b/ports/stm32/modnwcc3k.c index 8723994f45251..b3fd93922853c 100644 --- a/ports/stm32/modnwcc3k.c +++ b/ports/stm32/modnwcc3k.c @@ -443,7 +443,7 @@ STATIC mp_obj_t cc3k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); if (wlan_start(0) != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "failed to init CC3000 module")); + mp_raise_msg(&mp_type_OSError, "failed to init CC3000 module"); } // set connection policy. this should be called explicitly by the user diff --git a/ports/stm32/modusocket.c b/ports/stm32/modusocket.c index 5a163311379e4..46d7240ca88b9 100644 --- a/ports/stm32/modusocket.c +++ b/ports/stm32/modusocket.c @@ -425,7 +425,7 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { } if (!have_ip) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); + mp_raise_msg(&mp_type_OSError, "no available NIC"); } mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); diff --git a/ports/stm32/mpthreadport.c b/ports/stm32/mpthreadport.c index 7b3b92934b0f4..0077e13937070 100644 --- a/ports/stm32/mpthreadport.c +++ b/ports/stm32/mpthreadport.c @@ -75,7 +75,7 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { uint32_t id = pyb_thread_new(th, stack, stack_len, entry, arg); if (id == 0) { mp_thread_mutex_unlock(&thread_mutex); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); + mp_raise_msg(&mp_type_OSError, "can't create thread"); } mp_thread_mutex_unlock(&thread_mutex); diff --git a/py/objint.c b/py/objint.c index 6473767e41343..2fdcf5864f288 100644 --- a/py/objint.c +++ b/py/objint.c @@ -137,7 +137,7 @@ STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { mp_obj_t mp_obj_new_int_from_float(mp_float_t val) { int cl = fpclassify(val); if (cl == FP_INFINITE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "can't convert inf to int")); + mp_raise_msg(&mp_type_OverflowError, "can't convert inf to int"); } else if (cl == FP_NAN) { mp_raise_ValueError("can't convert NaN to int"); } else { From cddb2dd0c3f7d55599bdb0e1994f8b81f8b22d10 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Nov 2019 13:20:25 +1100 Subject: [PATCH 0683/1299] stm32/mpthreadport: Include runtime.h to get defn of mp_raise_msg. --- ports/stm32/mpthreadport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/mpthreadport.c b/ports/stm32/mpthreadport.c index 0077e13937070..4e1ebf064db54 100644 --- a/ports/stm32/mpthreadport.c +++ b/ports/stm32/mpthreadport.c @@ -26,7 +26,7 @@ #include -#include "py/mpstate.h" +#include "py/runtime.h" #include "py/gc.h" #include "py/mpthread.h" #include "gccollect.h" From d209f9ebe72aa2af0af72ed3bba737a47c45e567 Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Mon, 4 Nov 2019 20:50:50 +0100 Subject: [PATCH 0684/1299] esp32: Remove unused "esponewire.c" in favour of extmod/modonewire. --- ports/esp32/esponewire.c | 80 ---------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 ports/esp32/esponewire.c diff --git a/ports/esp32/esponewire.c b/ports/esp32/esponewire.c deleted file mode 100644 index 781616cbe4a7a..0000000000000 --- a/ports/esp32/esponewire.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015-2017 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/mphal.h" -#include "esp8266/esponewire.h" - -#define TIMING_RESET1 (0) -#define TIMING_RESET2 (1) -#define TIMING_RESET3 (2) -#define TIMING_READ1 (3) -#define TIMING_READ2 (4) -#define TIMING_READ3 (5) -#define TIMING_WRITE1 (6) -#define TIMING_WRITE2 (7) -#define TIMING_WRITE3 (8) - -uint16_t esp_onewire_timings[9] = {480, 40, 420, 5, 5, 40, 10, 50, 10}; - -#define DELAY_US mp_hal_delay_us_fast - -int esp_onewire_reset(mp_hal_pin_obj_t pin) { - mp_hal_pin_write(pin, 0); - DELAY_US(esp_onewire_timings[TIMING_RESET1]); - uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION(); - mp_hal_pin_write(pin, 1); - DELAY_US(esp_onewire_timings[TIMING_RESET2]); - int status = !mp_hal_pin_read(pin); - MICROPY_END_ATOMIC_SECTION(i); - DELAY_US(esp_onewire_timings[TIMING_RESET3]); - return status; -} - -int esp_onewire_readbit(mp_hal_pin_obj_t pin) { - mp_hal_pin_write(pin, 1); - uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION(); - mp_hal_pin_write(pin, 0); - DELAY_US(esp_onewire_timings[TIMING_READ1]); - mp_hal_pin_write(pin, 1); - DELAY_US(esp_onewire_timings[TIMING_READ2]); - int value = mp_hal_pin_read(pin); - MICROPY_END_ATOMIC_SECTION(i); - DELAY_US(esp_onewire_timings[TIMING_READ3]); - return value; -} - -void esp_onewire_writebit(mp_hal_pin_obj_t pin, int value) { - uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION(); - mp_hal_pin_write(pin, 0); - DELAY_US(esp_onewire_timings[TIMING_WRITE1]); - if (value) { - mp_hal_pin_write(pin, 1); - } - DELAY_US(esp_onewire_timings[TIMING_WRITE2]); - mp_hal_pin_write(pin, 1); - DELAY_US(esp_onewire_timings[TIMING_WRITE3]); - MICROPY_END_ATOMIC_SECTION(i); -} From 4f0f3dfb410062db4d41e42c2c7cff6c8b48f071 Mon Sep 17 00:00:00 2001 From: Jeremy Herbert Date: Mon, 4 Nov 2019 01:25:16 -0800 Subject: [PATCH 0685/1299] drivers/sdcard: Raise exception on timeout of readinto. Otherwise the code can get stuck in an infinite loop if the SD card fails to respond to a read. --- drivers/sdcard/sdcard.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py index ffc551d9ae9b4..fc67875566278 100644 --- a/drivers/sdcard/sdcard.py +++ b/drivers/sdcard/sdcard.py @@ -172,10 +172,13 @@ def readinto(self, buf): self.cs(0) # read until start byte (0xff) - while True: + for i in range(_CMD_TIMEOUT): self.spi.readinto(self.tokenbuf, 0xff) if self.tokenbuf[0] == _TOKEN_DATA: break + else: + self.cs(1) + raise OSError("timeout waiting for response") # read data mv = self.dummybuf_memoryview From 2f71d66ef7f6bfa93bdc51ab0eaf32cd03a81189 Mon Sep 17 00:00:00 2001 From: Mirko Vogt Date: Mon, 4 Nov 2019 23:16:37 +0000 Subject: [PATCH 0686/1299] tools/makemanifest.py: Follow symlinks when freezing linked directories. While the new manifest.py style got introduced for freezing python code into the resulting binary, the old way - where files and modules within ports/*/modules where baked into the resulting binary - was still supported via `freeze('$(PORT_DIR)/modules')` within manifest.py. However behaviour changed for symlinked directories (=modules), as those links weren't followed anymore. This commit restores the original behaviour by explicitly following symlinks within a modules/ directory --- tools/makemanifest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index 9889d50750273..a3aa42ca41d95 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -147,7 +147,7 @@ def get_timestamp(path, default=None): def get_timestamp_newest(path): ts_newest = 0 - for dirpath, dirnames, filenames in os.walk(path): + for dirpath, dirnames, filenames in os.walk(path, followlinks=True): for f in filenames: ts_newest = max(ts_newest, get_timestamp(os.path.join(dirpath, f))) return ts_newest @@ -171,7 +171,7 @@ def freeze_internal(kind, path, script, opt): raise FreezeError('can only freeze one str directory') manifest_list.append((KIND_AS_STR, path, script, opt)) elif script is None: - for dirpath, dirnames, filenames in os.walk(path): + for dirpath, dirnames, filenames in os.walk(path, followlinks=True): for f in filenames: freeze_internal(kind, path, (dirpath + '/' + f)[len(path) + 1:], opt) elif not isinstance(script, str): From 9b27069e2f6d5e754adc62b3aa20e14f5b10de66 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 17:16:30 +1100 Subject: [PATCH 0687/1299] extmod/vfs: Add autodetect of littlefs filesystem when mounting. --- extmod/vfs.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/extmod/vfs.c b/extmod/vfs.c index f99be3098b30b..5f5fc633d8c5a 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -38,6 +38,10 @@ #include "extmod/vfs_fat.h" #endif +#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 +#include "extmod/vfs_lfs.h" +#endif + #if MICROPY_VFS_POSIX #include "extmod/vfs_posix.h" #endif @@ -156,6 +160,44 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) { } } +STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { + #if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t vfs = MP_OBJ_NULL; + mp_vfs_blockdev_t blockdev; + mp_vfs_blockdev_init(&blockdev, bdev_obj); + uint8_t buf[44]; + mp_vfs_blockdev_read_ext(&blockdev, 0, 8, sizeof(buf), buf); + #if MICROPY_VFS_LFS1 + if (memcmp(&buf[32], "littlefs", 8) == 0) { + // LFS1 + vfs = mp_type_vfs_lfs1.make_new(&mp_type_vfs_lfs1, 1, 0, &bdev_obj); + nlr_pop(); + return vfs; + } + #endif + #if MICROPY_VFS_LFS2 + if (memcmp(&buf[0], "littlefs", 8) == 0) { + // LFS2 + vfs = mp_type_vfs_lfs2.make_new(&mp_type_vfs_lfs2, 1, 0, &bdev_obj); + nlr_pop(); + return vfs; + } + #endif + nlr_pop(); + } else { + // Ignore exception (eg block device doesn't support extended readblocks) + } + #endif + + #if MICROPY_VFS_FAT + return mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &bdev_obj); + #endif + + return bdev_obj; +} + mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_readonly, ARG_mkfs }; static const mp_arg_t allowed_args[] = { @@ -178,10 +220,7 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args if (dest[0] == MP_OBJ_NULL) { // Input object has no mount method, assume it's a block device and try to // auto-detect the filesystem and create the corresponding VFS entity. - // (At the moment we only support FAT filesystems.) - #if MICROPY_VFS_FAT - vfs_obj = mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &vfs_obj); - #endif + vfs_obj = mp_vfs_autodetect(vfs_obj); } // create new object From d01ca7888b8eeeed026270742c40efe442cdd6ef Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 17:17:10 +1100 Subject: [PATCH 0688/1299] esp32/esp32_partition: Support extended block protocol. --- ports/esp32/esp32_partition.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index 52b3859ff085e..e5bd31af0ec7c 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -148,26 +148,33 @@ STATIC mp_obj_t esp32_partition_info(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_info_obj, esp32_partition_info); -STATIC mp_obj_t esp32_partition_readblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf_in) { - esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint32_t offset = mp_obj_get_int(block_num) * BLOCK_SIZE_BYTES; +STATIC mp_obj_t esp32_partition_readblocks(size_t n_args, const mp_obj_t *args) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(args[0]); + uint32_t offset = mp_obj_get_int(args[1]) * BLOCK_SIZE_BYTES; mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); + if (n_args == 4) { + offset += mp_obj_get_int(args[3]); + } check_esp_err(esp_partition_read(self->part, offset, bufinfo.buf, bufinfo.len)); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_partition_readblocks_obj, esp32_partition_readblocks); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_partition_readblocks_obj, 3, 4, esp32_partition_readblocks); -STATIC mp_obj_t esp32_partition_writeblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf_in) { - esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint32_t offset = mp_obj_get_int(block_num) * BLOCK_SIZE_BYTES; +STATIC mp_obj_t esp32_partition_writeblocks(size_t n_args, const mp_obj_t *args) { + esp32_partition_obj_t *self = MP_OBJ_TO_PTR(args[0]); + uint32_t offset = mp_obj_get_int(args[1]) * BLOCK_SIZE_BYTES; mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - check_esp_err(esp_partition_erase_range(self->part, offset, bufinfo.len)); + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + if (n_args == 3) { + check_esp_err(esp_partition_erase_range(self->part, offset, bufinfo.len)); + } else { + offset += mp_obj_get_int(args[3]); + } check_esp_err(esp_partition_write(self->part, offset, bufinfo.buf, bufinfo.len)); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_partition_writeblocks_obj, esp32_partition_writeblocks); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_partition_writeblocks_obj, 3, 4, esp32_partition_writeblocks); STATIC mp_obj_t esp32_partition_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -178,6 +185,11 @@ STATIC mp_obj_t esp32_partition_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_ case MP_BLOCKDEV_IOCTL_SYNC: return MP_OBJ_NEW_SMALL_INT(0); case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(self->part->size / BLOCK_SIZE_BYTES); case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(BLOCK_SIZE_BYTES); + case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { + uint32_t offset = mp_obj_get_int(arg_in) * BLOCK_SIZE_BYTES; + check_esp_err(esp_partition_erase_range(self->part, offset, BLOCK_SIZE_BYTES)); + return MP_OBJ_NEW_SMALL_INT(0); + } default: return mp_const_none; } } From 4be316fb072ab7c2f28da815ead970ebf705c328 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 29 Oct 2019 17:17:22 +1100 Subject: [PATCH 0689/1299] esp32/moduos: Enable uos.VfsLfs2 for littlefs filesystems. This commit adds support for littlefs (v2) on all esp32 boards. The original FAT filesystem still works and any board with a preexisting FAT filesystem will still work as normal. It's possible to switch to littlefs by reformatting the block device using: import uos, flashbdev uos.VfsLfs2.mkfs(flashbdev.bdev) Then when the board reboots (soft or hard) the new littlefs filesystem will be mounted. It's possible to switch back to a FAT filesystem by formatting with uos.VfsFat.mkfs(flashbdev.bdev). --- ports/esp32/Makefile | 1 + ports/esp32/moduos.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 42b01a4e605bc..86e8cd3b26102 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -31,6 +31,7 @@ MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 MICROPY_FATFS = 1 MICROPY_PY_BTREE = 1 +MICROPY_VFS_LFS2 = 1 FROZEN_MANIFEST ?= boards/manifest.py diff --git a/ports/esp32/moduos.c b/ports/esp32/moduos.c index dc85136f3d717..d68df28fd550d 100644 --- a/ports/esp32/moduos.c +++ b/ports/esp32/moduos.c @@ -38,6 +38,7 @@ #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" +#include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" extern const mp_obj_type_t mp_fat_vfs_type; @@ -123,6 +124,12 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif + #if MICROPY_VFS_LFS1 + { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, + #endif + #if MICROPY_VFS_LFS2 + { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, + #endif #endif }; From f0e4677f0dafa027d3f534795a1849ad5430e98f Mon Sep 17 00:00:00 2001 From: Thea Flowers Date: Tue, 5 Nov 2019 17:11:10 -0800 Subject: [PATCH 0690/1299] py/emitnative: Fix typo, REG_PARENT_ARG_RET should be REG_PARENT_RET. --- py/emitnative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/emitnative.c b/py/emitnative.c index e038b87785d9a..fbf6659140383 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -2696,7 +2696,7 @@ STATIC void emit_native_return_value(emit_t *emit) { } if (return_vtype != VTYPE_PYOBJ) { emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, return_vtype, REG_ARG_2); - #if REG_RET != REG_PARENT_ARG_RET + #if REG_RET != REG_PARENT_RET ASM_MOV_REG_REG(emit->as, REG_PARENT_RET, REG_RET); #endif } From d2e6cfd8fd1044dead49cd95795a30c42c66463c Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 6 Nov 2019 12:06:10 +1100 Subject: [PATCH 0691/1299] tools/makemanifest.py: Skip freezing unsupported files with warning. --- tools/makemanifest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index a3aa42ca41d95..3a5e230d8a928 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -185,7 +185,8 @@ def freeze_internal(kind, path, script, opt): kind = k break else: - raise FreezeError('unsupported file type {}'.format(script)) + print('warn: unsupported file type, skipped freeze: {}'.format(script)) + return wanted_extension = extension_kind[kind] if not script.endswith(wanted_extension): raise FreezeError('expecting a {} file, got {}'.format(wanted_extension, script)) From 1295146a6f639091db854a6c3228ce84a35bf994 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 6 Nov 2019 17:08:28 +1100 Subject: [PATCH 0692/1299] docs/conf.py: Fix path to favicon.ico. --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 71e561c9c00b0..dbd1d0c562946 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -159,7 +159,7 @@ # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = 'favicon.ico' +html_favicon = 'static/favicon.ico' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, From 59850c0b83e738880c8ce56c39748ae2fcb7dce1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 6 Nov 2019 17:09:29 +1100 Subject: [PATCH 0693/1299] docs/templates/topindex.html: Replace usage of deprecated defindex.html. defindex.html (used by topindex.html) is deprecated, but topindex.html was already identical other than setting the title, so just inherit directly from layout.html. --- docs/templates/topindex.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/templates/topindex.html b/docs/templates/topindex.html index 08bf4c73e7923..ff766b0cf2ff0 100644 --- a/docs/templates/topindex.html +++ b/docs/templates/topindex.html @@ -1,4 +1,5 @@ -{% extends "defindex.html" %} +{% extends "layout.html" %} +{% set title = _('Overview') %} {% block body %}

MicroPython documentation

From d30b75e8f28b6e1593424b88b586072be4db6857 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 6 Nov 2019 17:09:51 +1100 Subject: [PATCH 0694/1299] docs/library/machine.SDCard.rst: Fix various typos. --- docs/library/machine.SDCard.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/library/machine.SDCard.rst b/docs/library/machine.SDCard.rst index 8398624c15c19..cf86b1fcb25e6 100644 --- a/docs/library/machine.SDCard.rst +++ b/docs/library/machine.SDCard.rst @@ -5,8 +5,8 @@ class SDCard -- secure digital memory card ========================================== SD cards are one of the most common small form factor removable storage media. -SD cards come in a variety of sizes and phsyical form factors. MMC cards are -similar removable storage devices while eMMC devices are electically similar +SD cards come in a variety of sizes and physical form factors. MMC cards are +similar removable storage devices while eMMC devices are electrically similar storage devices designed to be embedded into other systems. All three form share a common protocol for communication with their host system and high-level support looks the same for them all. As such in MicroPython they are implemented @@ -15,12 +15,12 @@ in a single class called :class:`machine.SDCard` . Both SD and MMC interfaces support being accessed with a variety of bus widths. When being accessed with a 1-bit wide interface they can be accessed using the SPI protocol. Different MicroPython hardware platforms support different widths -and pin configurations but for most platforms there is a standard configuation -for any given hardware. In general constructing an `SDCard`` object with without +and pin configurations but for most platforms there is a standard configuration +for any given hardware. In general constructing an ``SDCard`` object with without passing any parameters will initialise the interface to the default card slot for the current hardware. The arguments listed below represent the common -arguments that might need to be set in order to use either a non-stanard slot -or a non-standard pin assignment. The exact subset of arguments suported will +arguments that might need to be set in order to use either a non-standard slot +or a non-standard pin assignment. The exact subset of arguments supported will vary from platform to platform. .. class:: SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None) @@ -32,7 +32,7 @@ vary from platform to platform. uos.mount(machine.SDCard(), "/sd") - The constrcutor takes the following paramters: + The constructor takes the following parameters: - *slot* selects which of the available interfaces to use. Leaving this unset will select the default interface. From 6eee5413ff10a5e60ffd797d78a090c7edc6268e Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 7 Nov 2019 18:43:37 +1100 Subject: [PATCH 0695/1299] esp8266/modules/flashbdev.py: Support extended block protocol. --- ports/esp8266/modules/flashbdev.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ports/esp8266/modules/flashbdev.py b/ports/esp8266/modules/flashbdev.py index 80ddcfbf917bc..4273b2639c0f8 100644 --- a/ports/esp8266/modules/flashbdev.py +++ b/ports/esp8266/modules/flashbdev.py @@ -10,15 +10,17 @@ class FlashBdev: def __init__(self, blocks=NUM_BLK): self.blocks = blocks - def readblocks(self, n, buf): - #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf))) - esp.flash_read((n + self.START_SEC) * self.SEC_SIZE, buf) + def readblocks(self, n, buf, off=0): + #print("readblocks(%s, %x(%d), %d)" % (n, id(buf), len(buf), off)) + esp.flash_read((n + self.START_SEC) * self.SEC_SIZE + off, buf) - def writeblocks(self, n, buf): - #print("writeblocks(%s, %x(%d))" % (n, id(buf), len(buf))) + def writeblocks(self, n, buf, off=None): + #print("writeblocks(%s, %x(%d), %d)" % (n, id(buf), len(buf), off)) #assert len(buf) <= self.SEC_SIZE, len(buf) - esp.flash_erase(n + self.START_SEC) - esp.flash_write((n + self.START_SEC) * self.SEC_SIZE, buf) + if off is None: + esp.flash_erase(n + self.START_SEC) + off = 0 + esp.flash_write((n + self.START_SEC) * self.SEC_SIZE + off, buf) def ioctl(self, op, arg): #print("ioctl(%d, %r)" % (op, arg)) @@ -26,6 +28,9 @@ def ioctl(self, op, arg): return self.blocks if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE return self.SEC_SIZE + if op == 6: # MP_BLOCKDEV_IOCTL_BLOCK_ERASE + esp.flash_erase(arg + self.START_SEC) + return 0 size = esp.flash_size() if size < 1024*1024: From cea9209e0f16d0849426f418316eeafbc91f60dc Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 7 Nov 2019 18:44:16 +1100 Subject: [PATCH 0696/1299] esp8266/moduos: Add optional support for VfsLfs1 and VfsLfs2. With this commit an esp8266-based board can now be built with littlefs support via, eg "make MICROPY_VFS_LFS2=1". --- ports/esp8266/boards/esp8266_common.ld | 1 + ports/esp8266/moduos.c | 13 +++++++++++-- ports/esp8266/mpconfigport.h | 8 ++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ports/esp8266/boards/esp8266_common.ld b/ports/esp8266/boards/esp8266_common.ld index ce67e48048978..09896d5229a46 100644 --- a/ports/esp8266/boards/esp8266_common.ld +++ b/ports/esp8266/boards/esp8266_common.ld @@ -132,6 +132,7 @@ SECTIONS *lib/axtls/*.o(.literal*, .text*) *lib/berkeley-db-1.xx/*.o(.literal*, .text*) *lib/libm/*.o*(.literal*, .text*) + *lib/littlefs/*.o*(.literal*, .text*) *lib/mp-readline/*.o(.literal*, .text*) *lib/netutils/*.o*(.literal*, .text*) *lib/timeutils/*.o*(.literal*, .text*) diff --git a/ports/esp8266/moduos.c b/ports/esp8266/moduos.c index eab70e0638310..b66d5ccf4afc1 100644 --- a/ports/esp8266/moduos.c +++ b/ports/esp8266/moduos.c @@ -32,6 +32,7 @@ #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" +#include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" #include "esp_mphal.h" #include "user_interface.h" @@ -105,8 +106,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&os_dupterm_obj) }, { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, #endif - #if MICROPY_VFS_FAT - { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, + #if MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, @@ -119,6 +119,15 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, + #if MICROPY_VFS_FAT + { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, + #endif + #if MICROPY_VFS_LFS1 + { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, + #endif + #if MICROPY_VFS_LFS2 + { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, + #endif #endif }; diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 7263193928ffe..22ca99b2b18b7 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -137,8 +137,16 @@ void *esp_native_code_commit(void*, size_t); // printer for debugging output, goes to UART only extern const struct _mp_print_t mp_debug_print; +#if MICROPY_VFS_FAT #define mp_type_fileio mp_type_vfs_fat_fileio #define mp_type_textio mp_type_vfs_fat_textio +#elif MICROPY_VFS_LFS1 +#define mp_type_fileio mp_type_vfs_lfs1_fileio +#define mp_type_textio mp_type_vfs_lfs1_textio +#elif MICROPY_VFS_LFS2 +#define mp_type_fileio mp_type_vfs_lfs2_fileio +#define mp_type_textio mp_type_vfs_lfs2_textio +#endif // use vfs's functions for import stat and builtin open #define mp_import_stat mp_vfs_import_stat From 7e374d2317d869b3471c980e1e3cd65f2f43e450 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 7 Nov 2019 19:43:23 +1100 Subject: [PATCH 0697/1299] py/emitnx86: Make mp_f_n_args table match order of mp_fun_kind_t. --- py/emitnx86.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/py/emitnx86.c b/py/emitnx86.c index 0122e46bab5ee..790cae04c29e4 100644 --- a/py/emitnx86.c +++ b/py/emitnx86.c @@ -34,13 +34,11 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_BINARY_OP] = 3, [MP_F_BUILD_TUPLE] = 2, [MP_F_BUILD_LIST] = 2, - [MP_F_LIST_APPEND] = 2, [MP_F_BUILD_MAP] = 1, - [MP_F_STORE_MAP] = 3, - #if MICROPY_PY_BUILTINS_SET [MP_F_BUILD_SET] = 2, [MP_F_STORE_SET] = 2, - #endif + [MP_F_LIST_APPEND] = 2, + [MP_F_STORE_MAP] = 3, [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3, [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3, [MP_F_CALL_METHOD_N_KW] = 3, @@ -53,9 +51,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_IMPORT_NAME] = 3, [MP_F_IMPORT_FROM] = 2, [MP_F_IMPORT_ALL] = 1, - #if MICROPY_PY_BUILTINS_SLICE [MP_F_NEW_SLICE] = 3, - #endif [MP_F_UNPACK_SEQUENCE] = 3, [MP_F_UNPACK_EX] = 3, [MP_F_DELETE_NAME] = 1, @@ -66,6 +62,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_SMALL_INT_FLOOR_DIVIDE] = 2, [MP_F_SMALL_INT_MODULO] = 2, [MP_F_NATIVE_YIELD_FROM] = 3, + [MP_F_SETJMP] = 1, }; #define N_X86 (1) From 1266ba97545b66c93e33a2d4c4e665cdbd14228c Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 7 Nov 2019 18:22:42 +1100 Subject: [PATCH 0698/1299] examples/embedding: Remove obsolete fatfs files from build. --- examples/embedding/Makefile.upylib | 7 ------- 1 file changed, 7 deletions(-) diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib index 6d6302050cf78..0e388332e68fa 100644 --- a/examples/embedding/Makefile.upylib +++ b/examples/embedding/Makefile.upylib @@ -149,13 +149,6 @@ LIB_SRC_C = $(addprefix lib/,\ timeutils/timeutils.c \ ) -ifeq ($(MICROPY_FATFS),1) -LIB_SRC_C += $(addprefix lib/,\ - fatfs/ff.c \ - fatfs/option/ccsbcs.c \ - ) -endif - OBJ = $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) From 799b6d1e0c5bfb2392b7978f549ab2c7d2e0cc29 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 7 Nov 2019 18:27:51 +1100 Subject: [PATCH 0699/1299] extmod: Consolidate FAT FS config to MICROPY_VFS_FAT across all ports. This commit removes the Makefile-level MICROPY_FATFS config and moves the MICROPY_VFS_FAT config to the Makefile level to replace it. It also moves the include of the oofatfs source files in the build from each port to a central place in extmod/extmod.mk. For a port to enabled VFS FAT support it should now set MICROPY_VFS_FAT=1 at the level of the Makefile. This will include the relevant oofatfs files in the build and set MICROPY_VFS_FAT=1 at the C (preprocessor) level. --- extmod/extmod.mk | 15 ++++++++++++++- ports/esp32/Makefile | 8 +------- ports/esp32/mpconfigport.h | 1 - ports/esp8266/Makefile | 7 ------- ports/esp8266/boards/GENERIC/mpconfigboard.h | 1 - ports/esp8266/boards/GENERIC/mpconfigboard.mk | 1 + .../esp8266/boards/GENERIC_512K/mpconfigboard.mk | 2 +- ports/nrf/Makefile | 5 ++--- ports/nrf/README.md | 6 +++--- ports/nrf/mpconfigport.h | 1 - ports/stm32/Makefile | 5 +---- ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h | 1 - .../stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk | 3 +++ ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h | 1 - ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk | 3 +++ ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h | 1 - ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk | 3 +++ ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h | 1 - ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk | 3 +++ ports/stm32/mpconfigport.h | 3 --- ports/stm32/mpconfigport.mk | 3 +++ ports/unix/Makefile | 8 +------- ports/unix/mpconfigport.h | 1 - ports/unix/mpconfigport_coverage.h | 2 -- 24 files changed, 39 insertions(+), 46 deletions(-) create mode 100644 ports/esp8266/boards/GENERIC/mpconfigboard.mk diff --git a/extmod/extmod.mk b/extmod/extmod.mk index e714b602872dd..69d8cfad32b00 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -1,7 +1,20 @@ # This makefile fragment provides rules to build 3rd-party components for extmod modules +################################################################################ +# VFS FAT FS + +OOFATFS_DIR = lib/oofatfs + # this sets the config file for FatFs -CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" +CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\" + +ifeq ($(MICROPY_VFS_FAT),1) +CFLAGS_MOD += -DMICROPY_VFS_FAT=1 +SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\ + ff.c \ + ffunicode.c \ + ) +endif ################################################################################ # VFS littlefs diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 86e8cd3b26102..e3b14495d5fb5 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -29,8 +29,8 @@ QSTR_GLOBAL_REQUIREMENTS = $(SDKCONFIG_H) MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 -MICROPY_FATFS = 1 MICROPY_PY_BTREE = 1 +MICROPY_VFS_FAT = 1 MICROPY_VFS_LFS2 = 1 FROZEN_MANIFEST ?= boards/manifest.py @@ -348,12 +348,6 @@ LIB_SRC_C = $(addprefix lib/,\ utils/sys_stdio_mphal.c \ ) -ifeq ($(MICROPY_FATFS), 1) -LIB_SRC_C += \ - lib/oofatfs/ff.c \ - lib/oofatfs/ffunicode.c -endif - DRIVERS_SRC_C = $(addprefix drivers/,\ bus/softspi.c \ dht/dht.c \ diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 6cf86446b2c0b..da62beb4c1705 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -61,7 +61,6 @@ void *esp_native_code_commit(void*, size_t); #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_DEPTH (8) #define MICROPY_VFS (1) -#define MICROPY_VFS_FAT (1) // control over Python builtins #define MICROPY_PY_FUNCTION_ATTRS (1) diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index f1b718c781d95..f534eb6895073 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -22,7 +22,6 @@ QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h MICROPY_PY_USSL = 1 MICROPY_SSL_AXTLS = 1 AXTLS_DEFS_EXTRA = -Dabort=abort_ -DRT_MAX_PLAIN_LENGTH=1024 -DRT_EXTRA=4096 -MICROPY_FATFS ?= 1 MICROPY_PY_BTREE ?= 1 BTREE_DEFS_EXTRA = -DDEFPSIZE=1024 -DMINCACHE=3 @@ -147,12 +146,6 @@ LIB_SRC_C = $(addprefix lib/,\ utils/sys_stdio_mphal.c \ ) -ifeq ($(MICROPY_FATFS), 1) -LIB_SRC_C += \ - lib/oofatfs/ff.c \ - lib/oofatfs/ffunicode.c -endif - DRIVERS_SRC_C = $(addprefix drivers/,\ bus/softspi.c \ dht/dht.c \ diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.h b/ports/esp8266/boards/GENERIC/mpconfigboard.h index a7cacb815ee35..8f0505d074710 100644 --- a/ports/esp8266/boards/GENERIC/mpconfigboard.h +++ b/ports/esp8266/boards/GENERIC/mpconfigboard.h @@ -10,7 +10,6 @@ #define MICROPY_READER_VFS (MICROPY_VFS) #define MICROPY_VFS (1) -#define MICROPY_VFS_FAT (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.mk b/ports/esp8266/boards/GENERIC/mpconfigboard.mk new file mode 100644 index 0000000000000..86593ff60e9e2 --- /dev/null +++ b/ports/esp8266/boards/GENERIC/mpconfigboard.mk @@ -0,0 +1 @@ +MICROPY_VFS_FAT = 1 diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk index 90f3c1773de87..32fd4e0077a0f 100644 --- a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk +++ b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.mk @@ -1,3 +1,3 @@ -MICROPY_FATFS = 0 MICROPY_PY_BTREE = 0 +MICROPY_VFS_FAT = 0 LD_FILES = boards/esp8266_512k.ld diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 62208525fe0f2..2ac654911e3a9 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -43,8 +43,7 @@ include ../../py/py.mk GIT_SUBMODULES = lib/nrfx lib/tinyusb -MICROPY_FATFS ?= 0 -FATFS_DIR = lib/oofatfs +MICROPY_VFS_FAT ?= 0 MPY_CROSS = ../../mpy-cross/mpy-cross MPY_TOOL = ../../tools/mpy-tool.py @@ -318,7 +317,7 @@ OBJ += $(addprefix $(BUILD)/, $(SYSTEM_C_SRC:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o)) OBJ += $(BUILD)/pins_gen.o -$(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os +$(BUILD)/$(OOFATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os .PHONY: all flash deploy sd binary hex diff --git a/ports/nrf/README.md b/ports/nrf/README.md index 3c177c705c43b..b5f39267ebf2f 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -107,12 +107,12 @@ To use frozen modules, put them in a directory (e.g. `freeze/`) and supply make BOARD=pca10040 FROZEN_MPY_DIR=freeze -## Enable MICROPY_FATFS -As the `oofatfs` module is not having header guards that can exclude the implementation compile time, this port provides a flag to enable it explicitly. The MICROPY_FATFS is by default set to 0 and has to be set to 1 if `oofatfs` files should be compiled. This will be in addition of setting `MICROPY_VFS` and `MICROPY_VFS_FAT` in mpconfigport.h. +## Enable MICROPY_VFS_FAT +As the `oofatfs` module is not having header guards that can exclude the implementation compile time, this port provides a flag to enable it explicitly. The MICROPY_VFS_FAT is by default set to 0 and has to be set to 1 if `oofatfs` files should be compiled. This will be in addition of setting `MICROPY_VFS` in mpconfigport.h. For example: - make BOARD=pca10040 MICROPY_FATFS=1 + make BOARD=pca10040 MICROPY_VFS_FAT=1 ## Target Boards and Make Flags diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 71f9f6804d1b0..e5fa1579c5751 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -33,7 +33,6 @@ #ifndef MICROPY_VFS #define MICROPY_VFS (0) #endif -#define MICROPY_VFS_FAT (MICROPY_VFS) #define MICROPY_ALLOC_PATH_MAX (512) #define MICROPY_PERSISTENT_CODE_LOAD (0) #define MICROPY_EMIT_THUMB (0) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 99d2248fd4086..61ce06ca8c8a7 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -34,7 +34,6 @@ CMSIS_DIR=$(TOP)/lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Include HAL_DIR=lib/stm32lib/STM32$(MCU_SERIES_UPPER)xx_HAL_Driver USBDEV_DIR=usbdev #USBHOST_DIR=usbhost -FATFS_DIR=lib/oofatfs DFU=$(TOP)/tools/dfu.py # may need to prefix dfu-util with sudo USE_PYDFU ?= 1 @@ -128,8 +127,6 @@ MPY_CROSS_FLAGS += -march=armv7m SRC_LIB = $(addprefix lib/,\ libc/string0.c \ - oofatfs/ff.c \ - oofatfs/ffunicode.c \ mp-readline/readline.c \ netutils/netutils.c \ netutils/trace.c \ @@ -480,7 +477,7 @@ $(BUILD)/lib/libc/string0.o: COPT += -O2 # If we compile these using -O0 then it won't fit. So if you really want these # to be compiled with -O0, then edit boards/common.ld (in the .isr_vector section) # and comment out the following lines. -$(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os +$(BUILD)/$(OOFATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os $(PY_BUILD)/formatfloat.o: COPT += -Os $(PY_BUILD)/parsenum.o: COPT += -Os diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h index 7a80f26356520..25cfcbde76252 100644 --- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h @@ -14,7 +14,6 @@ #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) -#define MICROPY_VFS_FAT (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk index e2ced611837ee..03561f90ade3b 100644 --- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk +++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk @@ -4,5 +4,8 @@ MICROPY_FLOAT_IMPL = none AF_FILE = boards/stm32l072_af.csv LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld +# MicroPython settings +MICROPY_VFS_FAT = 0 + # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h index 366822d0d444c..fb8de60221e99 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h @@ -7,7 +7,6 @@ #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) -#define MICROPY_VFS_FAT (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk index 5efa0d4a5d468..984fe2f900540 100644 --- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk @@ -3,5 +3,8 @@ CMSIS_MCU = STM32F091xC AF_FILE = boards/stm32f091_af.csv LD_FILES = boards/stm32f091xc.ld boards/common_basic.ld +# MicroPython settings +MICROPY_VFS_FAT = 0 + # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h index e20dff677125b..e9753958dde1d 100644 --- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h @@ -14,7 +14,6 @@ #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) -#define MICROPY_VFS_FAT (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk index 5afe134ba0973..f3673f00601f0 100644 --- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk @@ -3,5 +3,8 @@ CMSIS_MCU = STM32L073xx AF_FILE = boards/stm32l072_af.csv LD_FILES = boards/stm32l072xz.ld boards/common_basic.ld +# MicroPython settings +MICROPY_VFS_FAT = 0 + # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h index e7202efe02c11..945cccb50682e 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.h @@ -8,7 +8,6 @@ #define MICROPY_PY_NETWORK (0) #define MICROPY_PY_STM (0) #define MICROPY_PY_PYB_LEGACY (0) -#define MICROPY_VFS_FAT (0) #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #define MICROPY_HW_ENABLE_RTC (1) diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk index 7c7cd34f0e0c1..6e220a4370db3 100644 --- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk @@ -4,5 +4,8 @@ AF_FILE = boards/stm32l432_af.csv LD_FILES = boards/stm32l432.ld boards/common_basic.ld OPENOCD_CONFIG = boards/openocd_stm32l4.cfg +# MicroPython settings +MICROPY_VFS_FAT = 0 + # Don't include default frozen modules because MCU is tight on flash space FROZEN_MANIFEST ?= diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 11c23723854a9..fc54026f6b720 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -84,9 +84,6 @@ #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_DEPTH (8) #define MICROPY_VFS (1) -#ifndef MICROPY_VFS_FAT -#define MICROPY_VFS_FAT (1) -#endif // control over Python builtins #define MICROPY_PY_FUNCTION_ATTRS (1) diff --git a/ports/stm32/mpconfigport.mk b/ports/stm32/mpconfigport.mk index e708de6c1b0e1..c6b3ddc74f4e0 100644 --- a/ports/stm32/mpconfigport.mk +++ b/ports/stm32/mpconfigport.mk @@ -8,3 +8,6 @@ MICROPY_PY_WIZNET5K ?= 0 # cc3k module for wifi support MICROPY_PY_CC3K ?= 0 + +# VFS FAT FS support +MICROPY_VFS_FAT ?= 1 diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 9a4453261cfc3..2fa1373e73912 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -163,12 +163,6 @@ LIB_SRC_C = $(addprefix lib/,\ timeutils/timeutils.c \ ) -# FatFS VFS support -LIB_SRC_C += $(addprefix lib/,\ - oofatfs/ff.c \ - oofatfs/ffunicode.c \ - ) - OBJ = $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) @@ -257,7 +251,7 @@ coverage: -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ -DMICROPY_UNIX_COVERAGE' \ LDFLAGS_EXTRA='-fprofile-arcs -ftest-coverage' \ - MICROPY_VFS_LFS1=1 MICROPY_VFS_LFS2=1 \ + MICROPY_VFS_FAT=1 MICROPY_VFS_LFS1=1 MICROPY_VFS_LFS2=1 \ FROZEN_MANIFEST=manifest_coverage.py \ BUILD=build-coverage PROG=micropython_coverage diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index e42ad5e49c147..40cd1f570252c 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -152,7 +152,6 @@ #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) #define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_VFS_FAT (0) // Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. // names in exception messages (may require more RAM). diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index afd364649077c..8a0bf3be48609 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -55,8 +55,6 @@ #define MICROPY_PY_URE_MATCH_SPAN_START_END (1) #define MICROPY_PY_URE_SUB (1) #define MICROPY_VFS_POSIX (1) -#undef MICROPY_VFS_FAT -#define MICROPY_VFS_FAT (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (1) #define MICROPY_PY_UCRYPTOLIB (1) From 71299d3224b6f8422f540c91cc0d3f0e89408e90 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 7 Nov 2019 22:00:01 +1100 Subject: [PATCH 0700/1299] esp32/boards/sdkconfig.base: Resize SSL output buffer from 16 to 4kiB. The IDF heap is more fragmented with IDF 4 and mbedtls cannot allocate enough RAM with 16+16kiB for both in and out buffers, so reduce output buffer size. Fixes issue #5303. --- ports/esp32/boards/sdkconfig.base | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index 9348f406324d8..2c77c209079ef 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -28,6 +28,10 @@ CONFIG_LWIP_PPP_SUPPORT=y CONFIG_LWIP_PPP_PAP_SUPPORT=y CONFIG_LWIP_PPP_CHAP_SUPPORT=y +# SSL +# Use 4kiB output buffer instead of default 16kiB (because IDF heap is fragmented in 4.0) +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y + # v3.3-only (renamed in 4.0) CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n From 258b1478307c1f9d89ed67309e145b9a55aeaadc Mon Sep 17 00:00:00 2001 From: Mike Causer Date: Fri, 8 Nov 2019 13:21:10 +1100 Subject: [PATCH 0701/1299] stm32/boards/stm32f405_af.csv: Fix typo in ETH_RMII_REF_CLK on PA1. --- ports/stm32/boards/stm32f405_af.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/stm32f405_af.csv b/ports/stm32/boards/stm32f405_af.csv index e6d8fcc2b5b6a..2602db877504d 100644 --- a/ports/stm32/boards/stm32f405_af.csv +++ b/ports/stm32/boards/stm32f405_af.csv @@ -1,7 +1,7 @@ Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, ,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11,I2C1/2/3,SPI1/SPI2/I2S2/I2S2ext,SPI3/I2Sext/I2S3,USART1/2/3/I2S3ext,UART4/5/USART6,CAN1/CAN2/TIM12/13/14,OTG_FS/OTG_HS,ETH,FSMC/SDIO/OTG_FS,DCMI,,,ADC PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0 -PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII__REF_CLK,,,,EVENTOUT,ADC123_IN1 +PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,,,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,,EVENTOUT,ADC123_IN1 PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,ETH_MDIO,,,,EVENTOUT,ADC123_IN2 PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,,EVENTOUT,ADC123_IN3 PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT,ADC12_IN4 From d667bc642ffb9603e85f50be73a32871427c5fa6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 12 Nov 2019 15:15:12 +1100 Subject: [PATCH 0702/1299] docs/library/ubluetooth: Fix name and link to FLAG_xxx constants. --- docs/library/ubluetooth.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index 5d44ffdb2943f..6e95a9e92e823 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -203,8 +203,8 @@ writes from a central to a given characteristic, use value. The **flags** are a bitwise-OR combination of the - :data:`ubluetooth.FLAGS_READ`, :data:`bluetooth.FLAGS_WRITE` and - :data:`ubluetooth.FLAGS_NOTIFY` values defined below. + :data:`ubluetooth.FLAG_READ`, :data:`ubluetooth.FLAG_WRITE` and + :data:`ubluetooth.FLAG_NOTIFY` values defined below. The return value is a list (one element per service) of tuples (each element is a value handle). Characteristics and descriptor handles are flattened From b2dd443d927ecd739111cdb0a0e94fe89c848312 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 11 Nov 2019 15:46:11 +0200 Subject: [PATCH 0703/1299] tools/makemanifest.py: Use sys.executable when invoking Python scripts. So the version of Python used to run makemanifest.py is also used for the sub-scripts. --- tools/makemanifest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/makemanifest.py b/tools/makemanifest.py index 3a5e230d8a928..90cec2bb481d0 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -270,13 +270,13 @@ def main(): return # Freeze paths as strings - res, output_str = system([MAKE_FROZEN] + str_paths) + res, output_str = system([sys.executable, MAKE_FROZEN] + str_paths) if res != 0: print('error freezing strings {}: {}'.format(str_paths, output_str)) sys.exit(1) # Freeze .mpy files - res, output_mpy = system([MPY_TOOL, '-f', '-q', args.build_dir + '/genhdr/qstrdefs.preprocessed.h'] + mpy_files) + res, output_mpy = system([sys.executable, MPY_TOOL, '-f', '-q', args.build_dir + '/genhdr/qstrdefs.preprocessed.h'] + mpy_files) if res != 0: print('error freezing mpy {}: {}'.format(mpy_files, output_mpy)) sys.exit(1) From 82d358510b38b092dac204786c193d8109dcf886 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Mon, 11 Nov 2019 15:57:34 +1300 Subject: [PATCH 0704/1299] esp32/rtc: Set system microseconds when setting time via RTC.datetime(). --- ports/esp32/machine_rtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c index 08c7b02bfd4c2..2cb30e75e25b2 100644 --- a/ports/esp32/machine_rtc.c +++ b/ports/esp32/machine_rtc.c @@ -103,6 +103,7 @@ STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *ar struct timeval tv = {0}; tv.tv_sec = timeutils_seconds_since_2000(mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]), mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6])); + tv.tv_usec = mp_obj_get_int(items[7]); settimeofday(&tv, NULL); return mp_const_none; From 1e87f11d3f2673ace3f36dd24bdc095bb25583e4 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 11 Nov 2019 15:44:04 +1100 Subject: [PATCH 0705/1299] py/objdict: Support ujson.dump() of OrderedDict objects. Following CPython, OrderedDict are dumped with the syntax of dict. --- py/objdict.c | 4 ++-- tests/extmod/ujson_dumps_ordereddict.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/extmod/ujson_dumps_ordereddict.py diff --git a/py/objdict.c b/py/objdict.c index 02a2346fdec1d..7a43a85485ccb 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -60,7 +60,7 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) { kind = PRINT_REPR; } - if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) { + if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) { mp_printf(print, "%q(", self->base.type->name); } mp_print_str(print, "{"); @@ -83,7 +83,7 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ mp_obj_print_helper(print, next->value, kind); } mp_print_str(print, "}"); - if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict) { + if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) { mp_print_str(print, ")"); } } diff --git a/tests/extmod/ujson_dumps_ordereddict.py b/tests/extmod/ujson_dumps_ordereddict.py new file mode 100644 index 0000000000000..c6f4a8fcb7942 --- /dev/null +++ b/tests/extmod/ujson_dumps_ordereddict.py @@ -0,0 +1,12 @@ +try: + import ujson as json + from ucollections import OrderedDict +except ImportError: + try: + import json + from collections import OrderedDict + except ImportError: + print("SKIP") + raise SystemExit + +print(json.dumps(OrderedDict(((1, 2), (3, 4))))) From 973f68780d2eb974e4921ffdf513079efc19e0a4 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 11 Nov 2019 12:51:23 +0200 Subject: [PATCH 0706/1299] qemu-arm: Add ldscript dependency in the final firmware.elf target. So that the target is rebuilt if the linker script changes. --- ports/qemu-arm/Makefile | 8 ++++++-- ports/qemu-arm/Makefile.test | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 92574d0e11451..e06e5dd5eed81 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -104,10 +104,14 @@ OBJ_COMMON += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ_RUN = OBJ_RUN += $(addprefix $(BUILD)/, $(SRC_RUN_C:.c=.o)) +ALL_OBJ_RUN = $(OBJ_COMMON) $(OBJ_RUN) + OBJ_TEST = OBJ_TEST += $(addprefix $(BUILD)/, $(SRC_TEST_C:.c=.o)) OBJ_TEST += $(BUILD)/tinytest.o +ALL_OBJ_TEST = $(OBJ_COMMON) $(OBJ_TEST) + # All object files, needed to get dependencies correct OBJ = $(OBJ_COMMON) $(OBJ_RUN) $(OBJ_TEST) @@ -127,8 +131,8 @@ run: $(BUILD)/firmware.elf qemu-system-arm -machine $(BOARD) $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< ## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here. -$(BUILD)/firmware.elf: $(OBJ_COMMON) $(OBJ_RUN) - $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) +$(BUILD)/firmware.elf: $(LDSCRIPT) $(ALL_OBJ_RUN) + $(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_RUN) $(LIBS) $(Q)$(SIZE) $@ include $(TOP)/py/mkrules.mk diff --git a/ports/qemu-arm/Makefile.test b/ports/qemu-arm/Makefile.test index 4204a84f0d44f..df0ba9939dfa6 100644 --- a/ports/qemu-arm/Makefile.test +++ b/ports/qemu-arm/Makefile.test @@ -16,8 +16,8 @@ $(BUILD)/genhdr/tests.h: $(BUILD)/tinytest.o: $(Q)$(CC) $(CFLAGS) -DNO_FORKING -o $@ -c $(TINYTEST)/tinytest.c -$(BUILD)/firmware-test.elf: $(OBJ_COMMON) $(OBJ_TEST) - $(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) +$(BUILD)/firmware-test.elf: $(LDSCRIPT) $(ALL_OBJ_TEST) + $(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_TEST) $(LIBS) $(Q)$(SIZE) $@ # Note: Using timeout(1) to handle cases where qemu hangs (e.g. this can happen with alignment errors). From 4f966892813b1b0c43f7ad1d97a7dcd77c646302 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 11 Nov 2019 17:07:11 +1100 Subject: [PATCH 0707/1299] py/ringbuf: Add peek16 method. --- py/ringbuf.c | 19 +++++++++++++------ py/ringbuf.h | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/py/ringbuf.c b/py/ringbuf.c index 8795e1eda99be..83887b300b453 100644 --- a/py/ringbuf.c +++ b/py/ringbuf.c @@ -26,6 +26,18 @@ #include "ringbuf.h" int ringbuf_get16(ringbuf_t *r) { + int v = ringbuf_peek16(r); + if (v == -1) { + return v; + } + r->iget += 2; + if (r->iget >= r->size) { + r->iget -= r->size; + } + return v; +} + +int ringbuf_peek16(ringbuf_t *r) { if (r->iget == r->iput) { return -1; } @@ -36,12 +48,7 @@ int ringbuf_get16(ringbuf_t *r) { if (iget_a == r->iput) { return -1; } - uint16_t v = (r->buf[r->iget] << 8) | (r->buf[iget_a]); - r->iget = iget_a + 1; - if (r->iget == r->size) { - r->iget = 0; - } - return v; + return (r->buf[r->iget] << 8) | (r->buf[iget_a]); } int ringbuf_put16(ringbuf_t *r, uint16_t v) { diff --git a/py/ringbuf.h b/py/ringbuf.h index 6b0d209bd1434..8d4ed164336ea 100644 --- a/py/ringbuf.h +++ b/py/ringbuf.h @@ -82,6 +82,7 @@ static inline size_t ringbuf_avail(ringbuf_t *r) { // Note: big-endian. No-op if not enough room available for both bytes. int ringbuf_get16(ringbuf_t *r); +int ringbuf_peek16(ringbuf_t *r); int ringbuf_put16(ringbuf_t *r, uint16_t v); #endif // MICROPY_INCLUDED_PY_RINGBUF_H From 334ba01c9078658d24e06b6ea68b7dc2ec02c506 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 11 Nov 2019 17:07:17 +1100 Subject: [PATCH 0708/1299] extmod/modbluetooth: Prioritise non-scan-result events. Remove existing scan result events from the ringbuf if the ringbuf is full and we're trying to enqueue any other event. This is needed so that events such as SCAN_COMPLETE are always put on the ringbuf. --- extmod/modbluetooth.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 1e5eafc89553a..e919a672e8516 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -792,13 +792,40 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event, bool *sched) { *sched = false; - if (o && ringbuf_free(&o->ringbuf) >= len + 2 && (o->irq_trigger & event) && o->irq_handler != mp_const_none) { - *sched = ringbuf_avail(&o->ringbuf) == 0; - ringbuf_put16(&o->ringbuf, event); - return true; - } else { + if (!o || !(o->irq_trigger & event) || o->irq_handler == mp_const_none) { return false; } + + if (ringbuf_free(&o->ringbuf) < len + 2) { + // Ringbuffer doesn't have room (and is therefore non-empty). + + // If this is another scan result, or the front of the ringbuffer isn't a scan result, then nothing to do. + if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT || ringbuf_peek16(&o->ringbuf) != MP_BLUETOOTH_IRQ_SCAN_RESULT) { + return false; + } + + // Front of the queue is a scan result, remove it. + + // event, addr_type, addr, connectable, rssi + int n = 2 + 1 + 6 + 1 + 1; + for (int i = 0; i < n; ++i) { + ringbuf_get(&o->ringbuf); + } + // adv_data + n = ringbuf_get(&o->ringbuf); + for (int i = 0; i < n; ++i) { + ringbuf_get(&o->ringbuf); + } + + // No need to schedule the handler, as the ringbuffer was non-empty. + } else { + // Schedule the handler only if this is the first thing in the ringbuffer. + *sched = ringbuf_avail(&o->ringbuf) == 0; + } + + // Append this event, the caller will then append the arguments. + ringbuf_put16(&o->ringbuf, event); + return true; } STATIC void schedule_ringbuf(bool sched) { From 2679c9e11608bb37360008ebed7336f8a231d09d Mon Sep 17 00:00:00 2001 From: Laurens Valk Date: Fri, 15 Nov 2019 14:15:15 +0100 Subject: [PATCH 0709/1299] unix/modtermios: Fix output speed setter in tcsetattr. The input speed was being set twice and the output speed was not set. --- ports/unix/modtermios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/unix/modtermios.c b/ports/unix/modtermios.c index d8a742a00ef59..85eabf399d9f7 100644 --- a/ports/unix/modtermios.c +++ b/ports/unix/modtermios.c @@ -96,7 +96,7 @@ STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t int res = cfsetispeed(&term, mp_obj_get_int(attrs->items[4])); RAISE_ERRNO(res, errno); - res = cfsetispeed(&term, mp_obj_get_int(attrs->items[5])); + res = cfsetospeed(&term, mp_obj_get_int(attrs->items[5])); RAISE_ERRNO(res, errno); res = tcsetattr(fd, when, &term); From 57c18fdd386064387a19271a3dbd3182ee5c44b0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 25 Sep 2019 17:11:56 +0200 Subject: [PATCH 0710/1299] py/compile: Coalesce error message for break/continue outside loop. To reduce code size. --- py/compile.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/py/compile.c b/py/compile.c index 2c818a9340929..0d36aef8b35ba 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1028,16 +1028,13 @@ STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { STATIC void compile_break_cont_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { uint16_t label; - const char *error_msg; if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_break_stmt) { label = comp->break_label; - error_msg = "'break' outside loop"; } else { label = comp->continue_label; - error_msg = "'continue' outside loop"; } if (label == INVALID_LABEL) { - compile_syntax_error(comp, (mp_parse_node_t)pns, error_msg); + compile_syntax_error(comp, (mp_parse_node_t)pns, "'break'/'continue' outside loop"); } assert(comp->cur_except_level >= comp->break_continue_except_level); EMIT_ARG(unwind_jump, label, comp->cur_except_level - comp->break_continue_except_level); From ed2314f35afc2d921e25e032f6b6b5556f43d5b1 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Mon, 12 Aug 2019 13:21:47 +1200 Subject: [PATCH 0711/1299] esp32/machine_rtc: Make RTC.memory size and availability configurable. The compile-time configuration value MICROPY_HW_RTC_USER_MEM_MAX can now be used to define the amount of memory set aside for RTC.memory(). If this value is configured to zero then the RTC.memory functionality is not included in the build. --- ports/esp32/machine_rtc.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c index 2cb30e75e25b2..b0268cd57fd30 100644 --- a/ports/esp32/machine_rtc.c +++ b/ports/esp32/machine_rtc.c @@ -44,17 +44,29 @@ typedef struct _machine_rtc_obj_t { mp_obj_base_t base; } machine_rtc_obj_t; -#define MEM_MAGIC 0x75507921 /* There is 8K of rtc_slow_memory, but some is used by the system software - If the USER_MAXLEN is set to high, the following compile error will happen: + If the MICROPY_HW_RTC_USER_MEM_MAX is set too high, the following compile error will happen: region `rtc_slow_seg' overflowed by N bytes The current system software allows almost 4096 to be used. To avoid running into issues if the system software uses more, 2048 was picked as a max length + + You can also change this max length at compile time by defining MICROPY_HW_RTC_USER_MEM_MAX + either on your make line, or in your board config. + + If MICROPY_HW_RTC_USER_MEM_MAX is set to 0, the RTC.memory() functionality will be not + be compiled which frees some extra flash and RTC memory. */ -#define MEM_USER_MAXLEN 2048 +#ifndef MICROPY_HW_RTC_USER_MEM_MAX +#define MICROPY_HW_RTC_USER_MEM_MAX 2048 +#endif + +// Optionally compile user memory functionality if the size of memory is greater than 0 +#if MICROPY_HW_RTC_USER_MEM_MAX > 0 +#define MEM_MAGIC 0x75507921 RTC_DATA_ATTR uint32_t rtc_user_mem_magic; RTC_DATA_ATTR uint32_t rtc_user_mem_len; -RTC_DATA_ATTR uint8_t rtc_user_mem_data[MEM_USER_MAXLEN]; +RTC_DATA_ATTR uint8_t rtc_user_mem_data[MICROPY_HW_RTC_USER_MEM_MAX]; +#endif // singleton RTC object STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}}; @@ -118,19 +130,23 @@ STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) { mp_obj_t args[2] = {self_in, date}; machine_rtc_datetime_helper(2, args); + #if MICROPY_HW_RTC_USER_MEM_MAX > 0 if (rtc_user_mem_magic != MEM_MAGIC) { rtc_user_mem_magic = MEM_MAGIC; rtc_user_mem_len = 0; } + #endif + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); +#if MICROPY_HW_RTC_USER_MEM_MAX > 0 STATIC mp_obj_t machine_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 1) { // read RTC memory uint32_t len = rtc_user_mem_len; - uint8_t rtcram[MEM_USER_MAXLEN]; + uint8_t rtcram[MICROPY_HW_RTC_USER_MEM_MAX]; memcpy( (char *) rtcram, (char *) rtc_user_mem_data, len); return mp_obj_new_bytes(rtcram, len); } else { @@ -138,7 +154,7 @@ STATIC mp_obj_t machine_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); - if (bufinfo.len > MEM_USER_MAXLEN) { + if (bufinfo.len > MICROPY_HW_RTC_USER_MEM_MAX) { mp_raise_ValueError("buffer too long"); } memcpy( (char *) rtc_user_mem_data, (char *) bufinfo.buf, bufinfo.len); @@ -147,11 +163,14 @@ STATIC mp_obj_t machine_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_memory_obj, 1, 2, machine_rtc_memory); +#endif STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) }, { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) }, + #if MICROPY_HW_RTC_USER_MEM_MAX > 0 { MP_ROM_QSTR(MP_QSTR_memory), MP_ROM_PTR(&machine_rtc_memory_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table); From 1530fda9cf27d793917ea00ad28fbe8d4955b232 Mon Sep 17 00:00:00 2001 From: Josh Lloyd Date: Thu, 21 Nov 2019 15:09:01 +1300 Subject: [PATCH 0712/1299] esp32/machine_rtc: Reduce memory footprint of user mem functionality. --- ports/esp32/machine_rtc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c index b0268cd57fd30..eaa70e2448ec9 100644 --- a/ports/esp32/machine_rtc.c +++ b/ports/esp32/machine_rtc.c @@ -64,7 +64,7 @@ typedef struct _machine_rtc_obj_t { #if MICROPY_HW_RTC_USER_MEM_MAX > 0 #define MEM_MAGIC 0x75507921 RTC_DATA_ATTR uint32_t rtc_user_mem_magic; -RTC_DATA_ATTR uint32_t rtc_user_mem_len; +RTC_DATA_ATTR uint16_t rtc_user_mem_len; RTC_DATA_ATTR uint8_t rtc_user_mem_data[MICROPY_HW_RTC_USER_MEM_MAX]; #endif @@ -145,10 +145,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init); STATIC mp_obj_t machine_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 1) { // read RTC memory - uint32_t len = rtc_user_mem_len; uint8_t rtcram[MICROPY_HW_RTC_USER_MEM_MAX]; - memcpy( (char *) rtcram, (char *) rtc_user_mem_data, len); - return mp_obj_new_bytes(rtcram, len); + memcpy((char*)rtcram, (char*)rtc_user_mem_data, rtc_user_mem_len); + return mp_obj_new_bytes(rtcram, rtc_user_mem_len); } else { // write RTC memory mp_buffer_info_t bufinfo; From d19c6d0519634851517bcf9e77f5d54d69084a5c Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Tue, 12 Nov 2019 15:29:24 +1100 Subject: [PATCH 0713/1299] extmod/modbluetooth: Create UUID from bytes and allow comparison ops. This allows construction of UUID objects from advertising data payloads and matching against known UUIDs. --- extmod/modbluetooth.c | 93 ++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index e919a672e8516..621b702f2e1bf 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -79,37 +79,6 @@ STATIC mp_obj_t bluetooth_handle_errno(int err) { // UUID object // ---------------------------------------------------------------------------- -// Parse string UUIDs, which are expected to be 128-bit UUIDs. -STATIC void mp_bluetooth_parse_uuid_128bit_str(mp_obj_t obj, uint8_t *uuid) { - size_t str_len; - const char *str_data = mp_obj_str_get_data(obj, &str_len); - int uuid_i = 32; - for (int i = 0; i < str_len; i++) { - char c = str_data[i]; - if (c == '-') { - continue; - } - if (!unichar_isxdigit(c)) { - mp_raise_ValueError("invalid char in UUID"); - } - c = unichar_xdigit_value(c); - uuid_i--; - if (uuid_i < 0) { - mp_raise_ValueError("UUID too long"); - } - if (uuid_i % 2 == 0) { - // lower nibble - uuid[uuid_i/2] |= c; - } else { - // upper nibble - uuid[uuid_i/2] = c << 4; - } - } - if (uuid_i > 0) { - mp_raise_ValueError("UUID too short"); - } -} - STATIC mp_obj_t bluetooth_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); @@ -125,8 +94,41 @@ STATIC mp_obj_t bluetooth_uuid_make_new(const mp_obj_type_t *type, size_t n_args self->data[0] = value & 0xff; self->data[1] = (value >> 8) & 0xff; } else { - self->type = MP_BLUETOOTH_UUID_TYPE_128; - mp_bluetooth_parse_uuid_128bit_str(all_args[0], self->data); + mp_buffer_info_t uuid_bufinfo = {0}; + mp_get_buffer_raise(all_args[0], &uuid_bufinfo, MP_BUFFER_READ); + if (uuid_bufinfo.len == 2 || uuid_bufinfo.len == 4 || uuid_bufinfo.len == 16) { + // Bytes data -- infer UUID type from length and copy data. + self->type = uuid_bufinfo.len; + memcpy(self->data, uuid_bufinfo.buf, self->type); + } else { + // Assume UUID string (e.g. '6E400001-B5A3-F393-E0A9-E50E24DCCA9E') + self->type = MP_BLUETOOTH_UUID_TYPE_128; + int uuid_i = 32; + for (int i = 0; i < uuid_bufinfo.len; i++) { + char c = ((char*)uuid_bufinfo.buf)[i]; + if (c == '-') { + continue; + } + if (!unichar_isxdigit(c)) { + mp_raise_ValueError("invalid char in UUID"); + } + c = unichar_xdigit_value(c); + uuid_i--; + if (uuid_i < 0) { + mp_raise_ValueError("UUID too long"); + } + if (uuid_i % 2 == 0) { + // lower nibble + self->data[uuid_i/2] |= c; + } else { + // upper nibble + self->data[uuid_i/2] = c << 4; + } + } + if (uuid_i > 0) { + mp_raise_ValueError("UUID too short"); + } + } } return self; @@ -143,6 +145,30 @@ STATIC mp_obj_t bluetooth_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } +STATIC mp_obj_t bluetooth_uuid_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + if (!mp_obj_is_type(rhs_in, &bluetooth_uuid_type)) { + return MP_OBJ_NULL; + } + + mp_obj_bluetooth_uuid_t *lhs = MP_OBJ_TO_PTR(lhs_in); + mp_obj_bluetooth_uuid_t *rhs = MP_OBJ_TO_PTR(rhs_in); + switch (op) { + case MP_BINARY_OP_EQUAL: + case MP_BINARY_OP_LESS: + case MP_BINARY_OP_LESS_EQUAL: + case MP_BINARY_OP_MORE: + case MP_BINARY_OP_MORE_EQUAL: + if (lhs->type == rhs->type) { + return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs->data, lhs->type, rhs->data, rhs->type)); + } else { + return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(lhs->type), MP_OBJ_NEW_SMALL_INT(rhs->type)); + } + + default: + return MP_OBJ_NULL; // op not supported + } +} + STATIC void bluetooth_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_bluetooth_uuid_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "UUID%u(%s", self->type * 8, self->type <= 4 ? "0x" : "'"); @@ -196,6 +222,7 @@ STATIC const mp_obj_type_t bluetooth_uuid_type = { .name = MP_QSTR_UUID, .make_new = bluetooth_uuid_make_new, .unary_op = bluetooth_uuid_unary_op, + .binary_op = bluetooth_uuid_binary_op, .locals_dict = NULL, .print = bluetooth_uuid_print, .buffer_p = { .get_buffer = bluetooth_uuid_get_buffer }, From 2ae755d9e1971437181097dbbf43e116ba8383d0 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 13 Nov 2019 11:53:41 +1100 Subject: [PATCH 0714/1299] extmod/modbluetooth_nimble: Make gap_scan_stop no-op if no scan ongoing. No need for this to throw an exception if the intent (don't be scanning) is clear, and avoids a race with the scan duration timeout. --- extmod/modbluetooth_nimble.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 33dac5a425caf..d0c3a3d81d4e6 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -659,6 +659,9 @@ int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_ } int mp_bluetooth_gap_scan_stop(void) { + if (!ble_gap_disc_active()) { + return 0; + } int err = ble_gap_disc_cancel(); if (err == 0) { mp_bluetooth_gap_on_scan_complete(); From 438c0dc2a4ab27883bab80a40372a44d7f5fe963 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 13 Nov 2019 16:59:23 +1100 Subject: [PATCH 0715/1299] extmod/modbluetooh_nimble: Fix UUID conversion for 16 and 32 bit values. --- extmod/modbluetooth_nimble.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index d0c3a3d81d4e6..f86ab70bf1e40 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -117,14 +117,14 @@ STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(const ble_uuid_any_t *uuid) { case BLE_UUID_TYPE_16: result.type = MP_BLUETOOTH_UUID_TYPE_16; result.data[0] = uuid->u16.value & 0xff; - result.data[1] = (uuid->u16.value << 8) & 0xff; + result.data[1] = (uuid->u16.value >> 8) & 0xff; break; case BLE_UUID_TYPE_32: result.type = MP_BLUETOOTH_UUID_TYPE_32; result.data[0] = uuid->u32.value & 0xff; - result.data[1] = (uuid->u32.value << 8) & 0xff; - result.data[2] = (uuid->u32.value << 16) & 0xff; - result.data[3] = (uuid->u32.value << 24) & 0xff; + result.data[1] = (uuid->u32.value >> 8) & 0xff; + result.data[2] = (uuid->u32.value >> 16) & 0xff; + result.data[3] = (uuid->u32.value >> 24) & 0xff; break; case BLE_UUID_TYPE_128: result.type = MP_BLUETOOTH_UUID_TYPE_128; From fbb7646e3bd6fd17b2c39ac40d537cc0b07af188 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 13 Nov 2019 17:02:50 +1100 Subject: [PATCH 0716/1299] stm32/nimble_hci_uart.c: Prevent scheduler running during CYW-BT wakeup. Using mp_hal_delay_ms allows the scheduler to run, which might result in another transmit operation happening, which would bypass the sleep (and fail). Use mp_hal_delay_us instead. --- ports/stm32/nimble_hci_uart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/nimble_hci_uart.c b/ports/stm32/nimble_hci_uart.c index defda1581e064..69e89e6abf6d5 100644 --- a/ports/stm32/nimble_hci_uart.c +++ b/ports/stm32/nimble_hci_uart.c @@ -162,7 +162,9 @@ void nimble_hci_uart_tx_strn(const char *str, uint len) { if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) { //printf("BT WAKE for TX\n"); mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up - mp_hal_delay_ms(5); // can't go lower than this + // Use delay_us rather than delay_ms to prevent running the scheduler (which + // might result in more BLE operations). + mp_hal_delay_us(5000); // can't go lower than this } #endif From e873d352ada8c392985e9f248271c5cf0fcd32ed Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 20 Nov 2019 10:45:14 +1100 Subject: [PATCH 0717/1299] extmod/modbluetooth: Simplify management of pre-allocated event data. The address, adv payload and uuid fields of the event are pre-allocated by modbluetooth, and reused in the IRQ handler. Simplify this and move all storage into the `mp_obj_bluetooth_ble_t` instance. This now allows users to hold on to a reference to these instances without crashes, although they may be overwritten by future events. If they want to hold onto the values longer term they need to copy them. --- docs/library/ubluetooth.rst | 6 +++++ extmod/modbluetooth.c | 46 +++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index 6e95a9e92e823..2d3af1bb6b0d5 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -52,6 +52,12 @@ Event Handling The optional *trigger* parameter allows you to set a mask of events that your program is interested in. The default is all events. + Note: the ``addr``, ``adv_data`` and ``uuid`` entries in the tuples are + references to data managed by the :mod:`ubluetooth` module (i.e. the same + instance will be re-used across multiple calls to the event handler). If + your program wants to use this data outside of the handler, then it must + copy them first, e.g. by using ``bytes(addr)`` or ``bluetooth.UUID(uuid)``. + An event handler showing all possible events:: def bt_irq(event, data): diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 621b702f2e1bf..bac7c07cbe959 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -59,11 +59,13 @@ STATIC const mp_obj_type_t bluetooth_uuid_type; typedef struct { mp_obj_base_t base; mp_obj_t irq_handler; - mp_obj_t irq_data_tuple; - uint8_t irq_addr_bytes[6]; - uint8_t irq_data_bytes[MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN]; - mp_obj_t irq_data_uuid; uint16_t irq_trigger; + mp_obj_t irq_data_tuple; + uint8_t irq_data_addr_bytes[6]; + uint8_t irq_data_data_bytes[MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN]; + mp_obj_str_t irq_data_addr; + mp_obj_str_t irq_data_data; + mp_obj_bluetooth_uuid_t irq_data_uuid; ringbuf_t ringbuf; } mp_obj_bluetooth_ble_t; @@ -234,16 +236,25 @@ STATIC const mp_obj_type_t bluetooth_uuid_type = { STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { if (MP_STATE_VM(bluetooth) == MP_OBJ_NULL) { - mp_obj_bluetooth_ble_t *o = m_new_obj(mp_obj_bluetooth_ble_t); + mp_obj_bluetooth_ble_t *o = m_new0(mp_obj_bluetooth_ble_t, 1); o->base.type = &bluetooth_ble_type; + o->irq_handler = mp_const_none; + o->irq_trigger = 0; + // Pre-allocate the event data tuple to prevent needing to allocate in the IRQ handler. o->irq_data_tuple = mp_obj_new_tuple(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN, NULL); - mp_obj_bluetooth_uuid_t *uuid = m_new_obj(mp_obj_bluetooth_uuid_t); - uuid->base.type = &bluetooth_uuid_type; - o->irq_data_uuid = MP_OBJ_FROM_PTR(uuid); - o->irq_trigger = 0; + + // Pre-allocated buffers for address, payload and uuid. + o->irq_data_addr.base.type = &mp_type_bytes; + o->irq_data_addr.data = o->irq_data_addr_bytes; + o->irq_data_data.base.type = &mp_type_bytes; + o->irq_data_data.data = o->irq_data_data_bytes; + o->irq_data_uuid.base.type = &bluetooth_uuid_type; + + // Allocate the ringbuf. TODO: Consider making the size user-specified. ringbuf_alloc(&o->ringbuf, MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); + MP_STATE_VM(bluetooth) = MP_OBJ_FROM_PTR(o); } return MP_STATE_VM(bluetooth); @@ -764,36 +775,31 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) { mp_obj_t handler = handler = o->irq_handler; mp_obj_tuple_t *data_tuple = MP_OBJ_TO_PTR(o->irq_data_tuple); - // Some events need to pass bytes objects to their handler, using the - // pre-allocated bytes array. - mp_obj_str_t irq_data_bytes_addr = {{&mp_type_bytes}, 0, 6, o->irq_addr_bytes}; - mp_obj_str_t irq_data_bytes_data = {{&mp_type_bytes}, 0, 0, o->irq_data_bytes}; - if (event == MP_BLUETOOTH_IRQ_CENTRAL_CONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT || event == MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT || event == MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT) { // conn_handle, addr_type, addr - ringbuf_extract(&o->ringbuf, data_tuple, 1, 1, &irq_data_bytes_addr, 0, 0, NULL, NULL); + ringbuf_extract(&o->ringbuf, data_tuple, 1, 1, &o->irq_data_addr, 0, 0, NULL, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTS_WRITE) { // conn_handle, value_handle ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, NULL, NULL); #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE } else if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT) { // addr_type, addr, connectable, rssi, adv_data - ringbuf_extract(&o->ringbuf, data_tuple, 0, 1, &irq_data_bytes_addr, 1, 1, NULL, &irq_data_bytes_data); + ringbuf_extract(&o->ringbuf, data_tuple, 0, 1, &o->irq_data_addr, 1, 1, NULL, &o->irq_data_data); } else if (event == MP_BLUETOOTH_IRQ_SCAN_COMPLETE) { // No params required. data_tuple->len = 0; } else if (event == MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT) { // conn_handle, start_handle, end_handle, uuid - ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, 0, MP_OBJ_TO_PTR(o->irq_data_uuid), NULL); + ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT) { // conn_handle, def_handle, value_handle, properties, uuid - ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, 0, MP_OBJ_TO_PTR(o->irq_data_uuid), NULL); + ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT) { // conn_handle, handle, uuid - ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, MP_OBJ_TO_PTR(o->irq_data_uuid), NULL); + ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, &o->irq_data_uuid, NULL); } else if (event == MP_BLUETOOTH_IRQ_GATTC_READ_RESULT || event == MP_BLUETOOTH_IRQ_GATTC_NOTIFY || event == MP_BLUETOOTH_IRQ_GATTC_INDICATE) { // conn_handle, value_handle, data - ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, NULL, &irq_data_bytes_data); + ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, 0, NULL, &o->irq_data_data); } else if (event == MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS) { // conn_handle, value_handle, status ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, 0, NULL, NULL); From 3436223630751c770c04b2dca35ef0002143f033 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 13 Nov 2019 17:00:35 +1100 Subject: [PATCH 0718/1299] examples/bluetooth: Add helpers for decoding advertising payloads. Extracts name and service UUID fields. --- examples/bluetooth/ble_advertising.py | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/examples/bluetooth/ble_advertising.py b/examples/bluetooth/ble_advertising.py index b57d5e031c2f1..3a06beb740389 100644 --- a/examples/bluetooth/ble_advertising.py +++ b/examples/bluetooth/ble_advertising.py @@ -2,6 +2,7 @@ from micropython import const import struct +import bluetooth # Advertising payloads are repeated packets of the following form: # 1 byte data length (N + 1) @@ -46,3 +47,39 @@ def _append(adv_type, value): _append(_ADV_TYPE_APPEARANCE, struct.pack(' Date: Wed, 13 Nov 2019 17:33:14 +1100 Subject: [PATCH 0719/1299] examples/bluetooth: Add example for reading temperature sensor. --- examples/bluetooth/ble_temperature_central.py | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 examples/bluetooth/ble_temperature_central.py diff --git a/examples/bluetooth/ble_temperature_central.py b/examples/bluetooth/ble_temperature_central.py new file mode 100644 index 0000000000000..3d609f13ca488 --- /dev/null +++ b/examples/bluetooth/ble_temperature_central.py @@ -0,0 +1,222 @@ +# This example finds and connects to a BLE temperature sensor (e.g. the one in ble_temperature.py). + +import bluetooth +import random +import struct +import time +import micropython + +from ble_advertising import decode_services, decode_name + +from micropython import const +_IRQ_CENTRAL_CONNECT = const(1 << 0) +_IRQ_CENTRAL_DISCONNECT = const(1 << 1) +_IRQ_GATTS_WRITE = const(1 << 2) +_IRQ_GATTS_READ_REQUEST = const(1 << 3) +_IRQ_SCAN_RESULT = const(1 << 4) +_IRQ_SCAN_COMPLETE = const(1 << 5) +_IRQ_PERIPHERAL_CONNECT = const(1 << 6) +_IRQ_PERIPHERAL_DISCONNECT = const(1 << 7) +_IRQ_GATTC_SERVICE_RESULT = const(1 << 8) +_IRQ_GATTC_CHARACTERISTIC_RESULT = const(1 << 9) +_IRQ_GATTC_DESCRIPTOR_RESULT = const(1 << 10) +_IRQ_GATTC_READ_RESULT = const(1 << 11) +_IRQ_GATTC_WRITE_STATUS = const(1 << 12) +_IRQ_GATTC_NOTIFY = const(1 << 13) +_IRQ_GATTC_INDICATE = const(1 << 14) +_IRQ_ALL = const(0xffff) + +# org.bluetooth.service.environmental_sensing +_ENV_SENSE_UUID = bluetooth.UUID(0x181A) +# org.bluetooth.characteristic.temperature +_TEMP_UUID = bluetooth.UUID(0x2A6E) +_TEMP_CHAR = (_TEMP_UUID, bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY,) +_ENV_SENSE_SERVICE = (_ENV_SENSE_UUID, (_TEMP_CHAR,),) + +# org.bluetooth.characteristic.gap.appearance.xml +_ADV_APPEARANCE_GENERIC_THERMOMETER = const(768) + +class BLETemperatureCentral: + def __init__(self, ble): + self._ble = ble + self._ble.active(True) + self._ble.irq(handler=self._irq) + + self._reset() + + def _reset(self): + # Cached name and address from a successful scan. + self._name = None + self._addr_type = None + self._addr = None + + # Cached value (if we have one) + self._value = None + + # Callbacks for completion of various operations. + # These reset back to None after being invoked. + self._scan_callback = None + self._conn_callback = None + self._read_callback = None + + # Persistent callback for when new data is notified from the device. + self._notify_callback = None + + # Connected device. + self._conn_handle = None + self._value_handle = None + + def _irq(self, event, data): + if event == _IRQ_SCAN_RESULT: + addr_type, addr, connectable, rssi, adv_data = data + if connectable and _ENV_SENSE_UUID in decode_services(adv_data): + # Found a potential device, remember it and stop scanning. + self._addr_type = addr_type + self._addr = bytes(addr) # Note: The addr buffer is owned by modbluetooth, need to copy it. + self._name = decode_name(adv_data) or '?' + self._ble.gap_scan(None) + + elif event == _IRQ_SCAN_COMPLETE: + if self._scan_callback: + if self._addr: + # Found a device during the scan (and the scan was explicitly stopped). + self._scan_callback(self._addr_type, self._addr, self._name) + self._scan_callback = None + else: + # Scan timed out. + self._scan_callback(None, None, None) + + elif event == _IRQ_PERIPHERAL_CONNECT: + # Connect successful. + conn_handle, addr_type, addr, = data + if addr_type == self._addr_type and addr == self._addr: + self._conn_handle = conn_handle + self._ble.gattc_discover_services(self._conn_handle) + + elif event == _IRQ_PERIPHERAL_DISCONNECT: + # Disconnect (either initiated by us or the remote end). + conn_handle, _, _, = data + if conn_handle == self._conn_handle: + # If it was initiated by us, it'll already be reset. + self._reset() + + elif event == _IRQ_GATTC_SERVICE_RESULT: + # Connected device returned a service. + conn_handle, start_handle, end_handle, uuid = data + if conn_handle == self._conn_handle and uuid == _ENV_SENSE_UUID: + self._ble.gattc_discover_characteristics(self._conn_handle, start_handle, end_handle) + + elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT: + # Connected device returned a characteristic. + conn_handle, def_handle, value_handle, properties, uuid = data + if conn_handle == self._conn_handle and uuid == _TEMP_UUID: + self._value_handle = value_handle + # We've finished connecting and discovering device, fire the connect callback. + if self._conn_callback: + self._conn_callback() + + elif event == _IRQ_GATTC_READ_RESULT: + # A read completed successfully. + conn_handle, value_handle, char_data = data + if conn_handle == self._conn_handle and value_handle == self._value_handle: + self._update_value(char_data) + if self._read_callback: + self._read_callback(self._value) + self._read_callback = None + + elif event == _IRQ_GATTC_NOTIFY: + # The ble_temperature.py demo periodically notifies its value. + conn_handle, value_handle, notify_data = data + if conn_handle == self._conn_handle and value_handle == self._value_handle: + self._update_value(notify_data) + if self._notify_callback: + self._notify_callback(self._value) + + + # Returns true if we've successfully connected and discovered characteristics. + def is_connected(self): + return self._conn_handle is not None and self._value_handle is not None + + # Find a device advertising the environmental sensor service. + def scan(self, callback=None): + self._addr_type = None + self._addr = None + self._scan_callback = callback + self._ble.gap_scan(2000, 30000, 30000) + + # Connect to the specified device (otherwise use cached address from a scan). + def connect(self, addr_type=None, addr=None, callback=None): + self._addr_type = addr_type or self._addr_type + self._addr = addr or self._addr + self._conn_callback = callback + if self._addr_type is None or self._addr is None: + return False + self._ble.gap_connect(self._addr_type, self._addr) + return True + + # Disconnect from current device. + def disconnect(self): + if not self._conn_handle: + return + self._ble.gap_disconnect(self._conn_handle) + self._reset() + + # Issues an (asynchronous) read, will invoke callback with data. + def read(self, callback): + if not self.is_connected(): + return + self._read_callback = callback + self._ble.gattc_read(self._conn_handle, self._value_handle) + + # Sets a callback to be invoked when the device notifies us. + def on_notify(self, callback): + self._notify_callback = callback + + def _update_value(self, data): + # Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius. + self._value = struct.unpack(' Date: Wed, 6 Nov 2019 13:48:35 +1100 Subject: [PATCH 0720/1299] stm32: Generalise flash mounting code so it supports arbitrary FS. This commit refactors and generalises the boot-mount routine on stm32 so that it can mount filesystems of arbitrary type. That is, it no longer assumes that the filesystem is FAT. It does this by using mp_vfs_mount() which does auto-detection of the filesystem type. --- ports/stm32/factoryreset.c | 32 ++++++++++++++ ports/stm32/factoryreset.h | 1 + ports/stm32/main.c | 91 ++++++++++++++++---------------------- ports/stm32/storage.c | 2 +- ports/stm32/storage.h | 1 + 5 files changed, 72 insertions(+), 55 deletions(-) diff --git a/ports/stm32/factoryreset.c b/ports/stm32/factoryreset.c index 24e0ff88cfbf5..513b521631d65 100644 --- a/ports/stm32/factoryreset.c +++ b/ports/stm32/factoryreset.c @@ -25,6 +25,11 @@ */ #include "py/runtime.h" +#include "py/mperrno.h" +#include "extmod/vfs_fat.h" +#include "systick.h" +#include "led.h" +#include "storage.h" #include "factoryreset.h" #if MICROPY_HW_ENABLE_STORAGE @@ -96,4 +101,31 @@ MP_WEAK void factory_reset_make_files(FATFS *fatfs) { } } +MP_WEAK int factory_reset_create_filesystem(void) { + // LED on to indicate creation of local filesystem + led_state(PYB_LED_GREEN, 1); + uint32_t start_tick = HAL_GetTick(); + + fs_user_mount_t vfs; + pyb_flash_init_vfs(&vfs); + uint8_t working_buf[FF_MAX_SS]; + FRESULT res = f_mkfs(&vfs.fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); + if (res != FR_OK) { + mp_printf(&mp_plat_print, "MPY: can't create flash filesystem\n"); + return -MP_ENODEV; + } + + // Set label + f_setlabel(&vfs.fatfs, MICROPY_HW_FLASH_FS_LABEL); + + // Populate the filesystem with factory files + factory_reset_make_files(&vfs.fatfs); + + // Keep LED on for at least 200ms + systick_wait_at_least(start_tick, 200); + led_state(PYB_LED_GREEN, 0); + + return 0; // success +} + #endif // MICROPY_HW_ENABLE_STORAGE diff --git a/ports/stm32/factoryreset.h b/ports/stm32/factoryreset.h index 85226f880bdb7..1d1f4b857165d 100644 --- a/ports/stm32/factoryreset.h +++ b/ports/stm32/factoryreset.h @@ -29,5 +29,6 @@ #include "lib/oofatfs/ff.h" void factory_reset_make_files(FATFS *fatfs); +int factory_reset_create_filesystem(void); #endif // MICROPY_INCLUDED_STM32_FACTORYRESET_H diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 3c6420d50d551..707b1fc68ee29 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" +#include "py/mperrno.h" #include "py/mphal.h" #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" @@ -81,10 +82,6 @@ STATIC pyb_thread_t pyb_thread_main; #endif -#if MICROPY_HW_ENABLE_STORAGE -STATIC fs_user_mount_t fs_user_mount_flash; -#endif - #if defined(MICROPY_HW_UART_REPL) #ifndef MICROPY_HW_UART_REPL_RXBUF #define MICROPY_HW_UART_REPL_RXBUF (260) @@ -159,65 +156,51 @@ STATIC mp_obj_t pyb_main(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a MP_DEFINE_CONST_FUN_OBJ_KW(pyb_main_obj, 1, pyb_main); #if MICROPY_HW_ENABLE_STORAGE +STATIC int vfs_mount_and_chdir(mp_obj_t bdev, mp_obj_t mount_point) { + nlr_buf_t nlr; + mp_int_t ret = -MP_EIO; + if (nlr_push(&nlr) == 0) { + mp_obj_t args[] = { bdev, mount_point }; + mp_vfs_mount(2, args, (mp_map_t*)&mp_const_empty_map); + mp_vfs_chdir(mount_point); + ret = 0; // success + nlr_pop(); + } else { + mp_obj_base_t *exc = nlr.ret_val; + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_OSError))) { + mp_obj_t v = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); + mp_obj_get_int_maybe(v, &ret); // get errno value + ret = -ret; + } + } + return ret; +} + // avoid inlining to avoid stack usage within main() MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { - // init the vfs object - fs_user_mount_t *vfs_fat = &fs_user_mount_flash; - vfs_fat->blockdev.flags = 0; - pyb_flash_init_vfs(vfs_fat); - - // try to mount the flash - FRESULT res = f_mount(&vfs_fat->fatfs); + if (reset_mode == 3) { + // Asked by user to reset filesystem + factory_reset_create_filesystem(); + } - if (reset_mode == 3 || res == FR_NO_FILESYSTEM) { - // no filesystem, or asked to reset it, so create a fresh one + // Try to mount the flash on "/flash" and chdir to it for the boot-up directory. + mp_obj_t bdev = MP_OBJ_FROM_PTR(&pyb_flash_obj); + mp_obj_t mount_point = MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash); + int ret = vfs_mount_and_chdir(bdev, mount_point); - // LED on to indicate creation of LFS - led_state(PYB_LED_GREEN, 1); - uint32_t start_tick = HAL_GetTick(); - - uint8_t working_buf[FF_MAX_SS]; - res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); - if (res == FR_OK) { - // success creating fresh LFS - } else { - printf("MPY: can't create flash filesystem\n"); - return false; + if (ret == -MP_ENODEV && reset_mode != 3) { + // No filesystem (and didn't already create one), try to create a fresh one + ret = factory_reset_create_filesystem(); + if (ret == 0) { + ret = vfs_mount_and_chdir(bdev, mount_point); } + } - // set label - f_setlabel(&vfs_fat->fatfs, MICROPY_HW_FLASH_FS_LABEL); - - // populate the filesystem with factory files - factory_reset_make_files(&vfs_fat->fatfs); - - // keep LED on for at least 200ms - systick_wait_at_least(start_tick, 200); - led_state(PYB_LED_GREEN, 0); - } else if (res == FR_OK) { - // mount sucessful - } else { - fail: + if (ret != 0) { printf("MPY: can't mount flash\n"); return false; } - // mount the flash device (there should be no other devices mounted at this point) - // we allocate this structure on the heap because vfs->next is a root pointer - mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); - if (vfs == NULL) { - goto fail; - } - vfs->str = "/flash"; - vfs->len = 6; - vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); - vfs->next = NULL; - MP_STATE_VM(vfs_mount_table) = vfs; - - // The current directory is used as the boot up directory. - // It is set to the internal flash filesystem by default. - MP_STATE_PORT(vfs_cur) = vfs; - return true; } #endif @@ -616,7 +599,7 @@ void stm32_main(uint32_t reset_mode) { // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { // if there is a file in the flash called "SKIPSD", then we don't mount the SD card - if (!mounted_flash || f_stat(&fs_user_mount_flash.fatfs, "/SKIPSD", NULL) != FR_OK) { + if (!mounted_flash || mp_vfs_import_stat("SKIPSD") == MP_IMPORT_STAT_FILE) { mounted_sdcard = init_sdcard_fs(); } } diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index d9d5464855894..905d51f325354 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -234,7 +234,7 @@ mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t // Expose the flash as an object with the block protocol. // there is a singleton Flash object -STATIC const mp_obj_base_t pyb_flash_obj = {&pyb_flash_type}; +const mp_obj_base_t pyb_flash_obj = {&pyb_flash_type}; STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments diff --git a/ports/stm32/storage.h b/ports/stm32/storage.h index 826b465a66d97..0ba3497a17a3a 100644 --- a/ports/stm32/storage.h +++ b/ports/stm32/storage.h @@ -63,6 +63,7 @@ int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uin int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks); extern const struct _mp_obj_type_t pyb_flash_type; +extern const struct _mp_obj_base_t pyb_flash_obj; struct _fs_user_mount_t; void pyb_flash_init_vfs(struct _fs_user_mount_t *vfs); From c169094f615c9337610703399be1cfb02a6ff120 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 13 Nov 2019 17:31:35 +1100 Subject: [PATCH 0721/1299] stm32/storage: Make pyb.Flash configurable, and support ext block proto. The pyb.Flash() class can now be used to construct objects which reference sections of the flash storage, starting at a certain offset and going for a certain length. Such objects also support the extended block protocol. The signature for the constructor is: pyb.Flash(start=-1, len=-1). --- ports/stm32/flashbdev.c | 40 ++++++++ ports/stm32/spibdev.c | 23 +++++ ports/stm32/storage.c | 196 ++++++++++++++++++++++++++++++++++++---- ports/stm32/storage.h | 11 ++- 4 files changed, 249 insertions(+), 21 deletions(-) diff --git a/ports/stm32/flashbdev.c b/ports/stm32/flashbdev.c index 15bf0d6b0a837..beb28c4925bd0 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -292,4 +292,44 @@ bool flash_bdev_writeblock(const uint8_t *src, uint32_t block) { return true; } +int flash_bdev_readblocks_ext(uint8_t *dest, uint32_t block, uint32_t offset, uint32_t len) { + // Get data from flash memory, possibly via cache + while (len) { + uint32_t l = MIN(len, FLASH_BLOCK_SIZE - offset); + uint32_t flash_addr = convert_block_to_flash_addr(block); + if (flash_addr == -1) { + // bad block number + return -1; + } + uint8_t *src = flash_cache_get_addr_for_read(flash_addr + offset); + memcpy(dest, src, l); + dest += l; + block += 1; + offset = 0; + len -= l; + } + return 0; +} + +int flash_bdev_writeblocks_ext(const uint8_t *src, uint32_t block, uint32_t offset, uint32_t len) { + // Copy to cache + while (len) { + uint32_t l = MIN(len, FLASH_BLOCK_SIZE - offset); + uint32_t flash_addr = convert_block_to_flash_addr(block); + if (flash_addr == -1) { + // bad block number + return -1; + } + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access + uint8_t *dest = flash_cache_get_addr_for_write(flash_addr + offset); + memcpy(dest, src, l); + restore_irq_pri(basepri); + src += l; + block += 1; + offset = 0; + len -= l; + } + return 0; +} + #endif // MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE diff --git a/ports/stm32/spibdev.c b/ports/stm32/spibdev.c index 9b5a10b400372..97ce885d453e8 100644 --- a/ports/stm32/spibdev.c +++ b/ports/stm32/spibdev.c @@ -55,6 +55,13 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) { restore_irq_pri(basepri); } return 0; + + case BDEV_IOCTL_BLOCK_ERASE: { + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access + mp_spiflash_erase_block(&bdev->spiflash, arg * MP_SPIFLASH_ERASE_BLOCK_SIZE); + restore_irq_pri(basepri); + return 0; + } } return -MP_EINVAL; } @@ -79,4 +86,20 @@ int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_nu return ret; } +int spi_bdev_readblocks_raw(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) { + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access + mp_spiflash_read(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, dest); + restore_irq_pri(basepri); + + return 0; +} + +int spi_bdev_writeblocks_raw(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) { + uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access + int ret = mp_spiflash_write(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, src); + restore_irq_pri(basepri); + + return ret; +} + #endif diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index 905d51f325354..0d3285ba051d7 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -28,6 +28,7 @@ #include #include "py/runtime.h" +#include "py/mperrno.h" #include "extmod/vfs_fat.h" #include "systick.h" @@ -233,41 +234,197 @@ mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t // // Expose the flash as an object with the block protocol. -// there is a singleton Flash object -const mp_obj_base_t pyb_flash_obj = {&pyb_flash_type}; +#ifdef MICROPY_HW_BDEV_SPIFLASH_EXTENDED +// Board defined an external SPI flash for use with extended block protocol +#define SPIFLASH (MICROPY_HW_BDEV_SPIFLASH_EXTENDED) +#define PYB_FLASH_NATIVE_BLOCK_SIZE (MP_SPIFLASH_ERASE_BLOCK_SIZE) +#define MICROPY_HW_BDEV_READBLOCKS_EXT(dest, bl, off, len) (spi_bdev_readblocks_raw(SPIFLASH, (dest), (bl), (off), (len))) +#define MICROPY_HW_BDEV_WRITEBLOCKS_EXT(dest, bl, off, len) (spi_bdev_writeblocks_raw(SPIFLASH, (dest), (bl), (off), (len))) + +#elif (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2) && MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE +// Board uses littlefs and internal flash, so enable extended block protocol on internal flash +#define PYB_FLASH_NATIVE_BLOCK_SIZE (FLASH_BLOCK_SIZE) +#define MICROPY_HW_BDEV_READBLOCKS_EXT(dest, bl, off, len) (flash_bdev_readblocks_ext((dest), (bl), (off), (len))) +#define MICROPY_HW_BDEV_WRITEBLOCKS_EXT(dest, bl, off, len) (flash_bdev_writeblocks_ext((dest), (bl), (off), (len))) +#endif + +#ifndef PYB_FLASH_NATIVE_BLOCK_SIZE +#define PYB_FLASH_NATIVE_BLOCK_SIZE (FLASH_BLOCK_SIZE) +#endif + +typedef struct _pyb_flash_obj_t { + mp_obj_base_t base; + uint32_t start; // in bytes + uint32_t len; // in bytes + #if defined(SPIFLASH) + bool use_native_block_size; + #endif +} pyb_flash_obj_t; + +// This Flash object represents the entire available flash, with emulated partition table at start +const pyb_flash_obj_t pyb_flash_obj = { + { &pyb_flash_type }, + -(FLASH_PART1_START_BLOCK * FLASH_BLOCK_SIZE), // to offset FLASH_PART1_START_BLOCK + 0, // actual size handled in ioctl, MP_BLOCKDEV_IOCTL_BLOCK_COUNT case +}; + +STATIC void pyb_flash_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pyb_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self == &pyb_flash_obj) { + mp_printf(print, "Flash()"); + } else { + mp_printf(print, "Flash(start=%u, len=%u)", self->start, self->len); + } +} + +STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // Parse arguments + enum { ARG_start, ARG_len }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_start, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_len, MP_ARG_INT, {.u_int = -1} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_start].u_int == -1 && args[ARG_len].u_int == -1) { + // Default singleton object that accesses entire flash, including virtual partition table + return MP_OBJ_FROM_PTR(&pyb_flash_obj); + } + + pyb_flash_obj_t *self = m_new_obj(pyb_flash_obj_t); + self->base.type = &pyb_flash_type; + #if defined(SPIFLASH) + self->use_native_block_size = false; + #endif + + uint32_t bl_len = (storage_get_block_count() - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE; + + mp_int_t start = args[ARG_start].u_int; + if (start == -1) { + start = 0; + } else if (!(0 <= start && start < bl_len && start % PYB_FLASH_NATIVE_BLOCK_SIZE == 0)) { + mp_raise_ValueError(NULL); + } + + mp_int_t len = args[ARG_len].u_int; + if (len == -1) { + len = bl_len - start; + } else if (!(0 < len && start + len <= bl_len && len % PYB_FLASH_NATIVE_BLOCK_SIZE == 0)) { + mp_raise_ValueError(NULL); + } -STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); + self->start = start; + self->len = len; - // return singleton object - return MP_OBJ_FROM_PTR(&pyb_flash_obj); + return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t pyb_flash_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { +STATIC mp_obj_t pyb_flash_readblocks(size_t n_args, const mp_obj_t *args) { + pyb_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); + uint32_t block_num = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = storage_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE); + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); + mp_uint_t ret = -MP_EIO; + if (n_args == 3) { + // Cast self->start to signed in case it's pyb_flash_obj with negative start + block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; + ret = storage_read_blocks(bufinfo.buf, block_num, bufinfo.len / FLASH_BLOCK_SIZE); + } + #if defined(MICROPY_HW_BDEV_READBLOCKS_EXT) + else if (self != &pyb_flash_obj) { + // Extended block read on a sub-section of the flash storage + uint32_t offset = mp_obj_get_int(args[3]); + block_num += self->start / PYB_FLASH_NATIVE_BLOCK_SIZE; + ret = MICROPY_HW_BDEV_READBLOCKS_EXT(bufinfo.buf, block_num, offset, bufinfo.len); + } + #endif return MP_OBJ_NEW_SMALL_INT(ret); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_readblocks_obj, pyb_flash_readblocks); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_flash_readblocks_obj, 3, 4, pyb_flash_readblocks); -STATIC mp_obj_t pyb_flash_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { +STATIC mp_obj_t pyb_flash_writeblocks(size_t n_args, const mp_obj_t *args) { + pyb_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]); + uint32_t block_num = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = storage_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_BLOCK_SIZE); + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + mp_uint_t ret = -MP_EIO; + if (n_args == 3) { + // Cast self->start to signed in case it's pyb_flash_obj with negative start + block_num += FLASH_PART1_START_BLOCK + (int32_t)self->start / FLASH_BLOCK_SIZE; + ret = storage_write_blocks(bufinfo.buf, block_num, bufinfo.len / FLASH_BLOCK_SIZE); + } + #if defined(MICROPY_HW_BDEV_WRITEBLOCKS_EXT) + else if (self != &pyb_flash_obj) { + // Extended block write on a sub-section of the flash storage + uint32_t offset = mp_obj_get_int(args[3]); + block_num += self->start / PYB_FLASH_NATIVE_BLOCK_SIZE; + ret = MICROPY_HW_BDEV_WRITEBLOCKS_EXT(bufinfo.buf, block_num, offset, bufinfo.len); + } + #endif return MP_OBJ_NEW_SMALL_INT(ret); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_writeblocks_obj, pyb_flash_writeblocks); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_flash_writeblocks_obj, 3, 4, pyb_flash_writeblocks); -STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { +STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { + pyb_flash_obj_t *self = self_in; mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { - case MP_BLOCKDEV_IOCTL_INIT: storage_init(); return MP_OBJ_NEW_SMALL_INT(0); + case MP_BLOCKDEV_IOCTL_INIT: { + mp_int_t ret = 0; + storage_init(); + if (mp_obj_get_int(arg_in) == 1) { + // Will be using extended block protocol + if (self == &pyb_flash_obj) { + ret = -1; + #if defined(SPIFLASH) + } else { + // Switch to use native block size of SPI flash + self->use_native_block_size = true; + #endif + } + } + return MP_OBJ_NEW_SMALL_INT(ret); + } case MP_BLOCKDEV_IOCTL_DEINIT: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly case MP_BLOCKDEV_IOCTL_SYNC: storage_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: return MP_OBJ_NEW_SMALL_INT(storage_get_block_count()); - case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(storage_get_block_size()); + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: { + mp_int_t n; + if (self == &pyb_flash_obj) { + // Get true size + n = storage_get_block_count(); + #if defined(SPIFLASH) + } else if (self->use_native_block_size) { + n = self->len / PYB_FLASH_NATIVE_BLOCK_SIZE; + #endif + } else { + n = self->len / FLASH_BLOCK_SIZE; + } + return MP_OBJ_NEW_SMALL_INT(n); + } + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: { + mp_int_t n = FLASH_BLOCK_SIZE; + #if defined(SPIFLASH) + if (self->use_native_block_size) { + n = PYB_FLASH_NATIVE_BLOCK_SIZE; + } + #endif + return MP_OBJ_NEW_SMALL_INT(n); + } + + case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: { + int ret = 0; + #if defined(SPIFLASH) + if (self->use_native_block_size) { + mp_int_t block_num = self->start / PYB_FLASH_NATIVE_BLOCK_SIZE + mp_obj_get_int(arg_in); + ret = spi_bdev_ioctl(SPIFLASH, BDEV_IOCTL_BLOCK_ERASE, block_num); + } + #endif + return MP_OBJ_NEW_SMALL_INT(ret); + } + default: return mp_const_none; } } @@ -284,6 +441,7 @@ STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table); const mp_obj_type_t pyb_flash_type = { { &mp_type_type }, .name = MP_QSTR_Flash, + .print = pyb_flash_print, .make_new = pyb_flash_make_new, .locals_dict = (mp_obj_dict_t*)&pyb_flash_locals_dict, }; diff --git a/ports/stm32/storage.h b/ports/stm32/storage.h index 0ba3497a17a3a..3a343b3275022 100644 --- a/ports/stm32/storage.h +++ b/ports/stm32/storage.h @@ -35,7 +35,8 @@ enum { BDEV_IOCTL_INIT = 1, BDEV_IOCTL_SYNC = 3, BDEV_IOCTL_NUM_BLOCKS = 4, - BDEV_IOCTL_IRQ_HANDLER = 6, + BDEV_IOCTL_BLOCK_ERASE = 6, + BDEV_IOCTL_IRQ_HANDLER = 7, }; void storage_init(void); @@ -52,6 +53,8 @@ mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t int32_t flash_bdev_ioctl(uint32_t op, uint32_t arg); bool flash_bdev_readblock(uint8_t *dest, uint32_t block); bool flash_bdev_writeblock(const uint8_t *src, uint32_t block); +int flash_bdev_readblocks_ext(uint8_t *dest, uint32_t block, uint32_t offset, uint32_t len); +int flash_bdev_writeblocks_ext(const uint8_t *src, uint32_t block, uint32_t offset, uint32_t len); typedef struct _spi_bdev_t { mp_spiflash_t spiflash; @@ -62,8 +65,12 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg); int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t num_blocks); int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks); +// These raw functions bypass the cache and go directly to SPI flash +int spi_bdev_readblocks_raw(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes); +int spi_bdev_writeblocks_raw(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes); + extern const struct _mp_obj_type_t pyb_flash_type; -extern const struct _mp_obj_base_t pyb_flash_obj; +extern const struct _pyb_flash_obj_t pyb_flash_obj; struct _fs_user_mount_t; void pyb_flash_init_vfs(struct _fs_user_mount_t *vfs); From 7897f5d9bea22a3a0d7474805af624d0683c6d52 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 13 Nov 2019 22:04:39 +1100 Subject: [PATCH 0722/1299] stm32/main: Auto detect block device used for main filesystem. --- ports/stm32/main.c | 51 ++++++++++++++++++++++++++++++++++++++++--- ports/stm32/storage.c | 2 -- ports/stm32/storage.h | 1 + 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 707b1fc68ee29..e2b3f3c36115e 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -35,8 +35,13 @@ #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" +#include "lib/littlefs/lfs1.h" +#include "lib/littlefs/lfs1_util.h" +#include "lib/littlefs/lfs2.h" +#include "lib/littlefs/lfs2_util.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" +#include "extmod/vfs_lfs.h" #if MICROPY_PY_LWIP #include "lwip/init.h" @@ -183,13 +188,53 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { factory_reset_create_filesystem(); } - // Try to mount the flash on "/flash" and chdir to it for the boot-up directory. + // Default block device to entire flash storage mp_obj_t bdev = MP_OBJ_FROM_PTR(&pyb_flash_obj); + + #if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 + + // Try to detect the block device used for the main filesystem, based on the first block + + uint8_t buf[FLASH_BLOCK_SIZE]; + storage_read_blocks(buf, FLASH_PART1_START_BLOCK, 1); + + mp_int_t len = -1; + + #if MICROPY_VFS_LFS1 + if (memcmp(&buf[40], "littlefs", 8) == 0) { + // LFS1 + lfs1_superblock_t *superblock = (void*)&buf[12]; + uint32_t block_size = lfs1_fromle32(superblock->d.block_size); + uint32_t block_count = lfs1_fromle32(superblock->d.block_count); + len = block_count * block_size; + } + #endif + + #if MICROPY_VFS_LFS2 + if (memcmp(&buf[8], "littlefs", 8) == 0) { + // LFS2 + lfs2_superblock_t *superblock = (void*)&buf[20]; + uint32_t block_size = lfs2_fromle32(superblock->block_size); + uint32_t block_count = lfs2_fromle32(superblock->block_count); + len = block_count * block_size; + } + #endif + + if (len != -1) { + // Detected a littlefs filesystem so create correct block device for it + mp_obj_t args[] = { MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(len) }; + bdev = pyb_flash_type.make_new(&pyb_flash_type, 2, 0, args); + } + + #endif + + // Try to mount the flash on "/flash" and chdir to it for the boot-up directory. mp_obj_t mount_point = MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash); int ret = vfs_mount_and_chdir(bdev, mount_point); - if (ret == -MP_ENODEV && reset_mode != 3) { - // No filesystem (and didn't already create one), try to create a fresh one + if (ret == -MP_ENODEV && bdev == MP_OBJ_FROM_PTR(&pyb_flash_obj) && reset_mode != 3) { + // No filesystem, bdev is still the default (so didn't detect a possibly corrupt littlefs), + // and didn't already create a filesystem, so try to create a fresh one now. ret = factory_reset_create_filesystem(); if (ret == 0) { ret = vfs_mount_and_chdir(bdev, mount_point); diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index 0d3285ba051d7..06dc8d6859385 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -41,8 +41,6 @@ #define STORAGE_SYSTICK_MASK (0x1ff) // 512ms #define STORAGE_IDLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & STORAGE_SYSTICK_MASK) == 0) -#define FLASH_PART1_START_BLOCK (0x100) - #if defined(MICROPY_HW_BDEV2_IOCTL) #define FLASH_PART2_START_BLOCK (FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV2_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) #endif diff --git a/ports/stm32/storage.h b/ports/stm32/storage.h index 3a343b3275022..2766ac59b3b1d 100644 --- a/ports/stm32/storage.h +++ b/ports/stm32/storage.h @@ -29,6 +29,7 @@ #include "drivers/memory/spiflash.h" #define FLASH_BLOCK_SIZE (512) +#define FLASH_PART1_START_BLOCK (0x100) // Try to match Python-level VFS block protocol where possible for these constants enum { From 715e4fc25f7b103da48c9bc9513ee76e12a1471a Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 13 Nov 2019 22:04:52 +1100 Subject: [PATCH 0723/1299] stm32/moduos: Add VfsLfs1 and VfsLfs2 to uos module, if enabled. --- ports/stm32/moduos.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/stm32/moduos.c b/ports/stm32/moduos.c index ead2380b33253..8bf58623c93d3 100644 --- a/ports/stm32/moduos.c +++ b/ports/stm32/moduos.c @@ -36,6 +36,7 @@ #include "extmod/misc.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" +#include "extmod/vfs_lfs.h" #include "genhdr/mpversion.h" #include "rng.h" #include "usb.h" @@ -174,6 +175,12 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { #if MICROPY_VFS_FAT { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, #endif + #if MICROPY_VFS_LFS1 + { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, + #endif + #if MICROPY_VFS_LFS2 + { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); From 5634a31a9835ead5bdf7bbff5380c878f16db56d Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 14 Nov 2019 16:30:10 +1100 Subject: [PATCH 0724/1299] extmod/vfs_lfs: Pass flag along to ioctl when init'ing bdev for lfs. To hint to the block device that the extended block protocol will be used. --- extmod/vfs_lfsx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index e5826803b2433..4f5ad5fdf7b46 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -73,7 +73,7 @@ STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx *self, mp_obj_t bdev, size_ config->erase = MP_VFS_LFSx(dev_erase); config->sync = MP_VFS_LFSx(dev_sync); - MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_INIT, 0, false); // initialise block device + MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_INIT, 1, false); // initialise block device int bs = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_SIZE, 0, true); // get block size int bc = MP_VFS_LFSx(dev_ioctl)(config, MP_BLOCKDEV_IOCTL_BLOCK_COUNT, 0, true); // get block count self->blockdev.block_size = bs; From 120368ba1ab444b2f1c17d1eb69bc6f09072ec5d Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 14 Nov 2019 16:36:05 +1100 Subject: [PATCH 0725/1299] stm32/boards: Enable LFS2 on PYBv1.x and PYBD boards. --- ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 1 + ports/stm32/boards/PYBD_SF2/mpconfigboard.mk | 1 + ports/stm32/boards/PYBV10/mpconfigboard.mk | 3 +++ ports/stm32/boards/PYBV11/mpconfigboard.mk | 3 +++ 4 files changed, 8 insertions(+) diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index 8926ec081be78..8e116bd02a59e 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -84,6 +84,7 @@ extern struct _spi_bdev_t spi_bdev; ) #define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n)) #define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n)) +#define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev) // for extended block protocol // SPI flash #2, to be memory mapped #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (24) diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk index 834a60b029ee8..9c0121f3137b6 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk @@ -16,3 +16,4 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 +MICROPY_VFS_LFS2 = 1 diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.mk b/ports/stm32/boards/PYBV10/mpconfigboard.mk index a4430cc1df0e4..cb78a7846d933 100644 --- a/ports/stm32/boards/PYBV10/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV10/mpconfigboard.mk @@ -11,3 +11,6 @@ LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif + +# MicroPython settings +MICROPY_VFS_LFS2 = 1 diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.mk b/ports/stm32/boards/PYBV11/mpconfigboard.mk index a4430cc1df0e4..cb78a7846d933 100644 --- a/ports/stm32/boards/PYBV11/mpconfigboard.mk +++ b/ports/stm32/boards/PYBV11/mpconfigboard.mk @@ -11,3 +11,6 @@ LD_FILES = boards/stm32f405.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08020000 endif + +# MicroPython settings +MICROPY_VFS_LFS2 = 1 From d8057c325a63d87b3e37cf4a6cdb04cb4eeba124 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 21 Nov 2019 16:11:59 +1100 Subject: [PATCH 0726/1299] stm32/storage: Change storage_read/write_blocks to return int type. And return -MP_EIO if calling storage_read_block/storage_write_block fails. This lines up with the return type and value (negative for error) of the calls to MICROPY_HW_BDEV_READBLOCKS (and WRITEBLOCKS, and BDEV2 versions). --- ports/stm32/storage.c | 8 ++++---- ports/stm32/storage.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index 06dc8d6859385..aecef8acc6eaa 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -185,7 +185,7 @@ bool storage_write_block(const uint8_t *src, uint32_t block) { } } -mp_uint_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { +int storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { #if defined(MICROPY_HW_BDEV_READBLOCKS) if (FLASH_PART1_START_BLOCK <= block_num && block_num + num_blocks <= FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV_READBLOCKS(dest, block_num - FLASH_PART1_START_BLOCK, num_blocks); @@ -200,13 +200,13 @@ mp_uint_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_bl for (size_t i = 0; i < num_blocks; i++) { if (!storage_read_block(dest + i * FLASH_BLOCK_SIZE, block_num + i)) { - return 1; // error + return -MP_EIO; // error } } return 0; // success } -mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { +int storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { #if defined(MICROPY_HW_BDEV_WRITEBLOCKS) if (FLASH_PART1_START_BLOCK <= block_num && block_num + num_blocks <= FLASH_PART1_START_BLOCK + MICROPY_HW_BDEV_IOCTL(BDEV_IOCTL_NUM_BLOCKS, 0)) { return MICROPY_HW_BDEV_WRITEBLOCKS(src, block_num - FLASH_PART1_START_BLOCK, num_blocks); @@ -221,7 +221,7 @@ mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t for (size_t i = 0; i < num_blocks; i++) { if (!storage_write_block(src + i * FLASH_BLOCK_SIZE, block_num + i)) { - return 1; // error + return -MP_EIO; // error } } return 0; // success diff --git a/ports/stm32/storage.h b/ports/stm32/storage.h index 2766ac59b3b1d..490fc4a09b8ac 100644 --- a/ports/stm32/storage.h +++ b/ports/stm32/storage.h @@ -47,9 +47,9 @@ void storage_flush(void); bool storage_read_block(uint8_t *dest, uint32_t block); bool storage_write_block(const uint8_t *src, uint32_t block); -// these return 0 on success, non-zero on error -mp_uint_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); +// these return 0 on success, negative errno on error +int storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); +int storage_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); int32_t flash_bdev_ioctl(uint32_t op, uint32_t arg); bool flash_bdev_readblock(uint8_t *dest, uint32_t block); From 6b3404f25e3d901d9b1313f2827a760093cddd92 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 22 Nov 2019 15:14:24 +1100 Subject: [PATCH 0727/1299] extmod/vfs_lfs: Fix bug when passing no args to constructor and mkfs. --- extmod/vfs_lfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c index d776849980942..f34d160f00538 100644 --- a/extmod/vfs_lfs.c +++ b/extmod/vfs_lfs.c @@ -33,7 +33,7 @@ enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead }; static const mp_arg_t lfs_make_allowed_args[] = { - { MP_QSTR_, MP_ARG_OBJ }, + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_readsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, { MP_QSTR_progsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, { MP_QSTR_lookahead, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 32} }, From a7bc4d1a1455a8a5cdea53d7a2caf03c9320f460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Nov 2019 14:06:49 +0100 Subject: [PATCH 0728/1299] py/builtinimport: Raise exception on empty module name. To prevent a crash returning MP_OBJ_NULL. A test is added for this case. --- py/builtinimport.c | 4 ++++ tests/import/builtin_import.py | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/py/builtinimport.c b/py/builtinimport.c index b9f6c2ab2dd23..9d91b20599955 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -334,6 +334,10 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { mod_len = new_mod_l; } + if (mod_len == 0) { + mp_raise_ValueError(NULL); + } + // check if module already exists qstr module_name_qstr = mp_obj_str_get_qstr(module_name); mp_obj_t module_obj = mp_module_get(module_name_qstr); diff --git a/tests/import/builtin_import.py b/tests/import/builtin_import.py index 088f631fcd3c4..157da983980ee 100644 --- a/tests/import/builtin_import.py +++ b/tests/import/builtin_import.py @@ -9,6 +9,12 @@ except TypeError: print('TypeError') +# module name should not be empty +try: + __import__("") +except ValueError: + print('ValueError') + # level argument should be non-negative try: __import__('xyz', None, None, None, -1) From bc129f1b84cc05ad92e6743b4f298e8aea5cbe50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 22 Nov 2019 10:07:08 +0100 Subject: [PATCH 0729/1299] py/qstr: Raise exception in qstr_from_strn if str to intern is too long. The string length being longer than the allowed qstr length can happen in many locations, for example in the parser with very long variable names. Without an explicit check that the length is within range (as done in this patch) the code would exhibit crashes and strange behaviour with truncated strings. --- py/qstr.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/py/qstr.c b/py/qstr.c index e6f86401a0316..29ffcae4081b6 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -31,6 +31,7 @@ #include "py/mpstate.h" #include "py/qstr.h" #include "py/gc.h" +#include "py/runtime.h" // NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings) // ultimately we will replace this with a static hash table of some kind @@ -192,12 +193,17 @@ qstr qstr_from_str(const char *str) { } qstr qstr_from_strn(const char *str, size_t len) { - assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN))); QSTR_ENTER(); qstr q = qstr_find_strn(str, len); if (q == 0) { // qstr does not exist in interned pool so need to add it + // check that len is not too big + if (len >= (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN))) { + QSTR_EXIT(); + mp_raise_msg(&mp_type_RuntimeError, "name too long"); + } + // compute number of bytes needed to intern this string size_t n_bytes = MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1; From 1675b98e74e6af0bd5edaf236a275dcb7735069e Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 22 Nov 2019 16:18:25 +1100 Subject: [PATCH 0730/1299] tests/stress: Add test for maximum length limit of qstrs. --- tests/stress/qstr_limit.py | 85 ++++++++++++++++++++++++++++++++++ tests/stress/qstr_limit.py.exp | 43 +++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 tests/stress/qstr_limit.py create mode 100644 tests/stress/qstr_limit.py.exp diff --git a/tests/stress/qstr_limit.py b/tests/stress/qstr_limit.py new file mode 100644 index 0000000000000..90c85dae962fe --- /dev/null +++ b/tests/stress/qstr_limit.py @@ -0,0 +1,85 @@ +# Test interning qstrs that go over the limit of the maximum qstr length +# (which is 255 bytes for the default configuration) + +def make_id(n, base='a'): + return ''.join(chr(ord(base) + i % 26) for i in range(n)) + +# identifiers in parser +for l in range(254, 259): + g = {} + var = make_id(l) + try: + exec(var + '=1', g) + except RuntimeError: + print('RuntimeError', l) + continue + print(var in g) + +# calling a function with kwarg +def f(**k): + print(k) +for l in range(254, 259): + try: + exec('f({}=1)'.format(make_id(l))) + except RuntimeError: + print('RuntimeError', l) + +# type construction +for l in range(254, 259): + id = make_id(l) + try: + print(type(id, (), {}).__name__) + except RuntimeError: + print('RuntimeError', l) + +# hasattr, setattr, getattr +class A: + pass +for l in range(254, 259): + id = make_id(l) + a = A() + try: + setattr(a, id, 123) + except RuntimeError: + print('RuntimeError', l) + try: + print(hasattr(a, id), getattr(a, id)) + except RuntimeError: + print('RuntimeError', l) + +# format with keys +for l in range(254, 259): + id = make_id(l) + try: + print(('{' + id + '}').format(**{id: l})) + except RuntimeError: + print('RuntimeError', l) + +# modulo format with keys +for l in range(254, 259): + id = make_id(l) + try: + print(('%(' + id + ')d') % {id: l}) + except RuntimeError: + print('RuntimeError', l) + +# import module +# (different OS's have different results so only print those that are consistent) +for l in range(150, 259): + try: + __import__(make_id(l)) + except ImportError: + if l < 152: + print('ok', l) + except RuntimeError: + if l > 255: + print('RuntimeError', l) + +# import package +for l in range(125, 130): + try: + exec('import ' + make_id(l) + '.' + make_id(l, 'A')) + except ImportError: + print('ok', l) + except RuntimeError: + print('RuntimeError', l) diff --git a/tests/stress/qstr_limit.py.exp b/tests/stress/qstr_limit.py.exp new file mode 100644 index 0000000000000..516c9d7f6c16b --- /dev/null +++ b/tests/stress/qstr_limit.py.exp @@ -0,0 +1,43 @@ +True +True +RuntimeError 256 +RuntimeError 257 +RuntimeError 258 +{'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst': 1} +{'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu': 1} +RuntimeError 256 +RuntimeError 257 +RuntimeError 258 +abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst +abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu +RuntimeError 256 +RuntimeError 257 +RuntimeError 258 +True 123 +True 123 +RuntimeError 256 +RuntimeError 256 +RuntimeError 257 +RuntimeError 257 +RuntimeError 258 +RuntimeError 258 +254 +255 +RuntimeError 256 +RuntimeError 257 +RuntimeError 258 +254 +255 +RuntimeError 256 +RuntimeError 257 +RuntimeError 258 +ok 150 +ok 151 +RuntimeError 256 +RuntimeError 257 +RuntimeError 258 +ok 125 +ok 126 +ok 127 +RuntimeError 128 +RuntimeError 129 From 4318a6d755b8365e4dfd4842c994003176cf6b70 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 25 Nov 2019 17:21:54 +0200 Subject: [PATCH 0731/1299] py/objstringio: Slightly optimize stringio_copy_on_write for code size. With the memcpy() call placed last it avoids the effects of registers clobbering. It's definitely effective in non-inlined functions, but even here it is still making a small difference. For example, on stm32, this saves an extra `ldr` instruction to load `o->vstr` after the memcpy() returns. --- py/objstringio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/objstringio.c b/py/objstringio.c index 8f1f7611389e8..cca4a81297dab 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -70,9 +70,9 @@ STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er STATIC void stringio_copy_on_write(mp_obj_stringio_t *o) { const void *buf = o->vstr->buf; o->vstr->buf = m_new(char, o->vstr->len); - memcpy(o->vstr->buf, buf, o->vstr->len); o->vstr->fixed_buf = false; o->ref_obj = MP_OBJ_NULL; + memcpy(o->vstr->buf, buf, o->vstr->len); } STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { From 797c2e8fc23ceeb9d6ce5079e2f82ee7b3431bee Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 26 Nov 2019 21:35:00 +1100 Subject: [PATCH 0732/1299] stm32/storage: Make start/len args of pyb.Flash keyword only. To allow the future possibility of initial positional args, like flash id. --- ports/stm32/storage.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index aecef8acc6eaa..ebb62e44cfe57 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -279,8 +279,8 @@ STATIC mp_obj_t pyb_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz // Parse arguments enum { ARG_start, ARG_len }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_start, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_len, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); From 01e5802ee39d8c5c18b2f24291776b6e9128d077 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 26 Nov 2019 21:36:41 +1100 Subject: [PATCH 0733/1299] py: Remove 3 obsolete commented-out lines from header files. --- py/lexer.h | 2 -- py/obj.h | 1 - py/runtime.h | 1 - 3 files changed, 4 deletions(-) diff --git a/py/lexer.h b/py/lexer.h index 34126a08fc23e..b9f97013a1bd9 100644 --- a/py/lexer.h +++ b/py/lexer.h @@ -184,8 +184,6 @@ void mp_lexer_to_next(mp_lexer_t *lex); // platform specific import function; must be implemented for a specific port // TODO tidy up, rename, or put elsewhere -//mp_lexer_t *mp_import_open_file(qstr mod_name); - typedef enum { MP_IMPORT_STAT_NO_EXIST, MP_IMPORT_STAT_DIR, diff --git a/py/obj.h b/py/obj.h index a22d5f8b810db..5b54892ce8090 100644 --- a/py/obj.h +++ b/py/obj.h @@ -691,7 +691,6 @@ mp_float_t mp_obj_get_float(mp_obj_t self_in); bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); #endif -//qstr mp_obj_get_qstr(mp_obj_t arg); void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items); // *items may point inside a GC block void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items); // *items may point inside a GC block size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice); diff --git a/py/runtime.h b/py/runtime.h index 1ac383ca71c59..b54b17b683951 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -151,7 +151,6 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name); void mp_import_all(mp_obj_t module); NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg); -//NORETURN void nlr_raise_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); NORETURN void mp_raise_ValueError(const char *msg); NORETURN void mp_raise_TypeError(const char *msg); NORETURN void mp_raise_NotImplementedError(const char *msg); From 77b8f86a5eae397c42c4c68fd9f86bbfa0311c82 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 27 Nov 2019 21:48:00 +1100 Subject: [PATCH 0734/1299] stm32/qstrdefsport.h: Remove unused qstrs and make USB ones conditional. qstrs in this file are always included in all builds, even if not used anywhere. So remove those that are never needed, and make USB names conditional on having USB enabled. --- ports/stm32/qstrdefsport.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/ports/stm32/qstrdefsport.h b/ports/stm32/qstrdefsport.h index 31220c5a42b23..857dc709c90a2 100644 --- a/ports/stm32/qstrdefsport.h +++ b/ports/stm32/qstrdefsport.h @@ -26,22 +26,18 @@ // qstrs specific to this port -Q(boot.py) -Q(main.py) // Entries for sys.path Q(/flash) Q(/flash/lib) Q(/sd) Q(/sd/lib) + +// For uos.sep +Q(/) + +#if MICROPY_HW_ENABLE_USB // for usb modes Q(MSC+HID) Q(VCP+MSC) Q(VCP+HID) -Q(CDC+MSC) -Q(CDC+HID) -Q(/) - - -// The following qstrings not referenced from anywhere in the sources -Q(CDC) -Q(flash) +#endif From 11c22430d4efe7eb8c87163faaae647b1e99abf8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 27 Nov 2019 21:50:30 +1100 Subject: [PATCH 0735/1299] stm32/boards/NUCLEO_L073RZ: Skip board-pin names for CPU only pins. This board doesn't have much flash and removing these unneeded names saves about 900 bytes of code size. --- ports/stm32/boards/NUCLEO_L073RZ/pins.csv | 104 +++++++++++----------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_L073RZ/pins.csv b/ports/stm32/boards/NUCLEO_L073RZ/pins.csv index 36d314108364f..7386425acf81a 100644 --- a/ports/stm32/boards/NUCLEO_L073RZ/pins.csv +++ b/ports/stm32/boards/NUCLEO_L073RZ/pins.csv @@ -33,55 +33,55 @@ SWDIO,PA13 SWCLK,PA14 USER_B1,PC13 LED_GREEN,PA5 -PA0,PA0 -PA1,PA1 -PA2,PA2 -PA3,PA3 -PA4,PA4 -PA5,PA5 -PA6,PA6 -PA7,PA7 -PA8,PA8 -PA9,PA9 -PA10,PA10 -PA11,PA11 -PA12,PA12 -PA13,PA13 -PA14,PA14 -PA15,PA15 -PB0,PB0 -PB1,PB1 -PB2,PB2 -PB3,PB3 -PB4,PB4 -PB5,PB5 -PB6,PB6 -PB7,PB7 -PB8,PB8 -PB9,PB9 -PB10,PB10 -PB11,PB11 -PB12,PB12 -PB13,PB13 -PB14,PB14 -PB15,PB15 -PC0,PC0 -PC1,PC1 -PC2,PC2 -PC3,PC3 -PC4,PC4 -PC5,PC5 -PC6,PC6 -PC7,PC7 -PC8,PC8 -PC9,PC9 -PC10,PC10 -PC11,PC11 -PC12,PC12 -PC13,PC13 -PC14,PC14 -PC15,PC15 -PD2,PD2 -PF0,PF0 -PF1,PF1 -PF11,PF11 +,PA0 +,PA1 +,PA2 +,PA3 +,PA4 +,PA5 +,PA6 +,PA7 +,PA8 +,PA9 +,PA10 +,PA11 +,PA12 +,PA13 +,PA14 +,PA15 +,PB0 +,PB1 +,PB2 +,PB3 +,PB4 +,PB5 +,PB6 +,PB7 +,PB8 +,PB9 +,PB10 +,PB11 +,PB12 +,PB13 +,PB14 +,PB15 +,PC0 +,PC1 +,PC2 +,PC3 +,PC4 +,PC5 +,PC6 +,PC7 +,PC8 +,PC9 +,PC10 +,PC11 +,PC12 +,PC13 +,PC14 +,PC15 +,PD2 +,PF0 +,PF1 +,PF11 From ba5e4841ecdfc83b6473bf4c5d1725c6069c6567 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 27 Nov 2019 22:47:05 +1100 Subject: [PATCH 0736/1299] stm32/main: Fix auto creation of pyb.Flash on boot with kw-only args. --- ports/stm32/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index e2b3f3c36115e..8cb6ed1e3bd53 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -222,8 +222,8 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { if (len != -1) { // Detected a littlefs filesystem so create correct block device for it - mp_obj_t args[] = { MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(len) }; - bdev = pyb_flash_type.make_new(&pyb_flash_type, 2, 0, args); + mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR_len), MP_OBJ_NEW_SMALL_INT(len) }; + bdev = pyb_flash_type.make_new(&pyb_flash_type, 0, 1, args); } #endif From 7f24c297787cd4bd92647f407017acbecdb0f949 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 28 Nov 2019 13:11:51 +1100 Subject: [PATCH 0737/1299] tools/mpy-tool.py: Support qstr linking when freezing Xtensa native mpy. --- tools/mpy-tool.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 9b0b8e8cd2bf2..581603249d346 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -428,9 +428,11 @@ def __init__(self, code_kind, fun_data, prelude_offset, prelude, qstr_links, qst else: self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",%progbits @ ")))' - # Allow single-byte alignment by default for x86/x64/xtensa, but on ARM we need halfword- or word- alignment. - if config.native_arch == MP_NATIVE_ARCH_ARMV6: - # ARMV6 -- four byte align. + # Allow single-byte alignment by default for x86/x64. + # ARM needs word alignment, ARM Thumb needs halfword, due to instruction size. + # Xtensa needs word alignment due to the 32-bit constant table embedded in the code. + if config.native_arch in (MP_NATIVE_ARCH_ARMV6, MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN): + # ARMV6 or Xtensa -- four byte align. self.fun_data_attributes += ' __attribute__ ((aligned (4)))' elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: # ARMVxxM -- two byte align. @@ -452,8 +454,11 @@ def _link_qstr(self, pc, kind, qst): is_obj = kind == 2 if is_obj: qst = '((uintptr_t)MP_OBJ_NEW_QSTR(%s))' % qst - if config.native_arch in (MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64): - print(' %s & 0xff, %s >> 8, 0, 0,' % (qst, qst)) + if config.native_arch in ( + MP_NATIVE_ARCH_X86, MP_NATIVE_ARCH_X64, + MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN + ): + print(' %s & 0xff, (%s >> 8) & 0xff, (%s >> 16) & 0xff, %s >> 24,' % (qst, qst, qst, qst)) return 4 elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: if is_obj: From d6e051082af51566d4a16dc90f89da75a5007c06 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 29 Nov 2019 11:33:29 +1100 Subject: [PATCH 0738/1299] extmod/modbluetooth: Simplify how BLE IRQ callback is scheduled. Instead of enqueue_irq() inspecting the ringbuf to decide whether to schedule the IRQ callback (if ringbuf is empty), maintain a flag that knows if the callback is on the schedule queue or not. This saves about 150 bytes of code (for stm32 builds), and simplifies all uses of enqueue_irq() and schedule_ringbuf(). --- extmod/modbluetooth.c | 66 ++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index bac7c07cbe959..cb014bd9edd4b 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -60,6 +60,7 @@ typedef struct { mp_obj_base_t base; mp_obj_t irq_handler; uint16_t irq_trigger; + bool irq_scheduled; mp_obj_t irq_data_tuple; uint8_t irq_data_addr_bytes[6]; uint8_t irq_data_data_bytes[MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN]; @@ -757,9 +758,12 @@ STATIC void ringbuf_extract(ringbuf_t* ringbuf, mp_obj_tuple_t *data_tuple, size STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) { // This is always executing in schedule context. + + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + o->irq_scheduled = false; + for (;;) { MICROPY_PY_BLUETOOTH_ENTER - mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); mp_int_t event = event = ringbuf_get16(&o->ringbuf); if (event < 0) { @@ -822,9 +826,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv // Callbacks are called in interrupt context (i.e. can't allocate), so we need to push the data // into the ringbuf and schedule the callback via mp_sched_schedule. -STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event, bool *sched) { - *sched = false; - +STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event) { if (!o || !(o->irq_trigger & event) || o->irq_handler == mp_const_none) { return false; } @@ -849,11 +851,6 @@ STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event, b for (int i = 0; i < n; ++i) { ringbuf_get(&o->ringbuf); } - - // No need to schedule the handler, as the ringbuffer was non-empty. - } else { - // Schedule the handler only if this is the first thing in the ringbuffer. - *sched = ringbuf_avail(&o->ringbuf) == 0; } // Append this event, the caller will then append the arguments. @@ -861,8 +858,10 @@ STATIC bool enqueue_irq(mp_obj_bluetooth_ble_t *o, size_t len, uint16_t event, b return true; } -STATIC void schedule_ringbuf(bool sched) { - if (sched) { +STATIC void schedule_ringbuf(void) { + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + if (!o->irq_scheduled) { + o->irq_scheduled = true; mp_sched_schedule(MP_OBJ_FROM_PTR(MP_ROM_PTR(&bluetooth_ble_invoke_irq_obj)), mp_const_none); } } @@ -870,47 +869,43 @@ STATIC void schedule_ringbuf(bool sched) { void mp_bluetooth_gap_on_connected_disconnected(uint16_t event, uint16_t conn_handle, uint8_t addr_type, const uint8_t *addr) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; - if (enqueue_irq(o, 2 + 1 + 6, event, &sched)) { + if (enqueue_irq(o, 2 + 1 + 6, event)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put(&o->ringbuf, addr_type); for (int i = 0; i < 6; ++i) { ringbuf_put(&o->ringbuf, addr[i]); } } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; - if (enqueue_irq(o, 2 + 2, MP_BLUETOOTH_IRQ_GATTS_WRITE, &sched)) { + if (enqueue_irq(o, 2 + 2, MP_BLUETOOTH_IRQ_GATTS_WRITE)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE void mp_bluetooth_gap_on_scan_complete(void) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; - if (enqueue_irq(o, 0, MP_BLUETOOTH_IRQ_SCAN_COMPLETE, &sched)) { + if (enqueue_irq(o, 0, MP_BLUETOOTH_IRQ_SCAN_COMPLETE)) { } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, bool connectable, const int8_t rssi, const uint8_t *data, size_t data_len) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); - if (enqueue_irq(o, 1 + 6 + 1 + 1 + 1 + data_len, MP_BLUETOOTH_IRQ_SCAN_RESULT, &sched)) { + if (enqueue_irq(o, 1 + 6 + 1 + 1 + 1 + data_len, MP_BLUETOOTH_IRQ_SCAN_RESULT)) { ringbuf_put(&o->ringbuf, addr_type); for (int i = 0; i < 6; ++i) { ringbuf_put(&o->ringbuf, addr[i]); @@ -923,58 +918,54 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, boo ringbuf_put(&o->ringbuf, data[i]); } } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; - if (enqueue_irq(o, 2 + 2 + 2 + 1 + service_uuid->type, MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, &sched)) { + if (enqueue_irq(o, 2 + 2 + 2 + 1 + service_uuid->type, MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, start_handle); ringbuf_put16(&o->ringbuf, end_handle); ringbuf_put_uuid(&o->ringbuf, service_uuid); } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; - if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, &sched)) { + if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, def_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put(&o->ringbuf, properties); ringbuf_put_uuid(&o->ringbuf, characteristic_uuid); } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; - if (enqueue_irq(o, 2 + 2 + 1 + descriptor_uuid->type, MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT, &sched)) { + if (enqueue_irq(o, 2 + 2 + 1 + descriptor_uuid->type, MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, handle); ringbuf_put_uuid(&o->ringbuf, descriptor_uuid); } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t *data, size_t data_len) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); - if (enqueue_irq(o, 2 + 2 + 1 + data_len, event, &sched)) { + if (enqueue_irq(o, 2 + 2 + 1 + data_len, event)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put(&o->ringbuf, data_len); @@ -982,21 +973,20 @@ void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, ringbuf_put(&o->ringbuf, data[i]); } } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - bool sched; - if (enqueue_irq(o, 2 + 2 + 2, MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS, &sched)) { + if (enqueue_irq(o, 2 + 2 + 2, MP_BLUETOOTH_IRQ_GATTC_WRITE_STATUS)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put16(&o->ringbuf, status); } + schedule_ringbuf(); MICROPY_PY_BLUETOOTH_EXIT - schedule_ringbuf(sched); } #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE From 8ce69288e9151d6bd5c218cde171d7d7dad9afd2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 29 Nov 2019 12:36:32 +1100 Subject: [PATCH 0739/1299] extmod/modbluetooth: Remove limit on data coming from gattc data input. This removes the limit on data coming in from a BLE.gattc_read() request, or a notify with payload (coming in to a central). In both cases the data coming in to the BLE callback is now limited only by the available data in the ringbuf, whereas before it was capped at (default hard coded) 20 bytes. --- extmod/modbluetooth.c | 26 ++++++++++++++------------ extmod/modbluetooth.h | 12 +++++++++++- extmod/modbluetooth_nimble.c | 33 +++++++++++++++++++-------------- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index cb014bd9edd4b..96cd41ae4566e 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -42,12 +42,6 @@ #error modbluetooth requires MICROPY_ENABLE_SCHEDULER #endif -// This is used to protect the ringbuffer. -#ifndef MICROPY_PY_BLUETOOTH_ENTER -#define MICROPY_PY_BLUETOOTH_ENTER mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); -#define MICROPY_PY_BLUETOOTH_EXIT MICROPY_END_ATOMIC_SECTION(atomic_state); -#endif - #define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000 #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5 @@ -961,20 +955,28 @@ void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t hand MICROPY_PY_BLUETOOTH_EXIT } -void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t *data, size_t data_len) { - MICROPY_PY_BLUETOOTH_ENTER +size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); if (enqueue_irq(o, 2 + 2 + 1 + data_len, event)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); ringbuf_put(&o->ringbuf, data_len); - for (int i = 0; i < data_len; ++i) { - ringbuf_put(&o->ringbuf, data[i]); - } + return data_len; + } else { + return 0; } +} + +void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len) { + mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); + for (int i = 0; i < data_len; ++i) { + ringbuf_put(&o->ringbuf, data[i]); + } +} + +void mp_bluetooth_gattc_on_data_available_end(void) { schedule_ringbuf(); - MICROPY_PY_BLUETOOTH_EXIT } void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status) { diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index bce28a6d15526..8a3ab414fdcb9 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -47,6 +47,12 @@ #define MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK (0) #endif +// This is used to protect the ringbuffer. +#ifndef MICROPY_PY_BLUETOOTH_ENTER +#define MICROPY_PY_BLUETOOTH_ENTER mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); +#define MICROPY_PY_BLUETOOTH_EXIT MICROPY_END_ATOMIC_SECTION(atomic_state); +#endif + // Common constants. #ifndef MP_BLUETOOTH_MAX_ATTR_SIZE #define MP_BLUETOOTH_MAX_ATTR_SIZE (20) @@ -247,7 +253,11 @@ void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid); // Notify modbluetooth that a read has completed with data (or notify/indicate data available, use `event` to disambiguate). -void mp_bluetooth_gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t *data, size_t data_len); +// Note: these functions are to be called in a group protected by MICROPY_PY_BLUETOOTH_ENTER/EXIT. +// _start returns the number of bytes to submit to the calls to _chunk, followed by a call to _end. +size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len); +void mp_bluetooth_gattc_on_data_available_chunk(const uint8_t *data, size_t data_len); +void mp_bluetooth_gattc_on_data_available_end(void); // Notify modbluetooth that a write has completed. void mp_bluetooth_gattc_on_write_status(uint16_t conn_handle, uint16_t value_handle, uint16_t status); diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index f86ab70bf1e40..83eb4b88a64a0 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -616,6 +616,20 @@ int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE +STATIC void gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16_t value_handle, const struct os_mbuf *om) { + MICROPY_PY_BLUETOOTH_ENTER + size_t len = OS_MBUF_PKTLEN(om); + len = mp_bluetooth_gattc_on_data_available_start(event, conn_handle, value_handle, len); + while (len > 0 && om != NULL) { + size_t n = MIN(om->om_len, len); + mp_bluetooth_gattc_on_data_available_chunk(OS_MBUF_DATA(om, const uint8_t*), n); + len -= n; + om = SLIST_NEXT(om, om_next); + } + mp_bluetooth_gattc_on_data_available_end(); + MICROPY_PY_BLUETOOTH_EXIT +} + STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->type == BLE_GAP_EVENT_DISC ? event->disc.event_type : -1); @@ -674,8 +688,6 @@ int mp_bluetooth_gap_scan_stop(void) { STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("peripheral_gap_event_cb: event=%d\n", event->type); struct ble_gap_conn_desc desc; - uint8_t buf[MP_BLUETOOTH_MAX_ATTR_SIZE]; - size_t len; uint8_t addr[6] = {0}; switch (event->type) { @@ -698,15 +710,11 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { break; - case BLE_GAP_EVENT_NOTIFY_RX: - len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(event->notify_rx.om)); - os_mbuf_copydata(event->notify_rx.om, 0, len, buf); - if (event->notify_rx.indication == 0) { - mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_NOTIFY, event->notify_rx.conn_handle, event->notify_rx.attr_handle, buf, len); - } else { - mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_INDICATE, event->notify_rx.conn_handle, event->notify_rx.attr_handle, buf, len); - } + case BLE_GAP_EVENT_NOTIFY_RX: { + uint16_t ev = event->notify_rx.indication == 0 ? MP_BLUETOOTH_IRQ_GATTC_NOTIFY : MP_BLUETOOTH_IRQ_GATTC_INDICATE; + gattc_on_data_available(ev, event->notify_rx.conn_handle, event->notify_rx.attr_handle, event->notify_rx.om); break; + } case BLE_GAP_EVENT_CONN_UPDATE: // TODO @@ -790,10 +798,7 @@ STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_err DEBUG_EVENT_printf("ble_gatt_attr_read_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); // TODO: Maybe send NULL if error->status non-zero. if (error->status == 0) { - uint8_t buf[MP_BLUETOOTH_MAX_ATTR_SIZE]; - size_t len = MIN(MP_BLUETOOTH_MAX_ATTR_SIZE, OS_MBUF_PKTLEN(attr->om)); - os_mbuf_copydata(attr->om, 0, len, buf); - mp_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, buf, len); + gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, attr->om); } return 0; } From 82a19cb39f1312a6349c481663905477c878a38d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 3 Dec 2019 12:32:29 +1100 Subject: [PATCH 0740/1299] mpy-cross: Support armv7em, armv7emsp, armv7emdp architectures. --- mpy-cross/main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mpy-cross/main.c b/mpy-cross/main.c index 4a4fccb3b745f..e82277220bf73 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -109,7 +109,7 @@ STATIC int usage(char **argv) { "-msmall-int-bits=number : set the maximum bits used to encode a small-int\n" "-mno-unicode : don't support unicode in compiled strings\n" "-mcache-lookup-bc : cache map lookups in the bytecode\n" -"-march= : set architecture for native emitter; x86, x64, armv6, armv7m, xtensa, xtensawin\n" +"-march= : set architecture for native emitter; x86, x64, armv6, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin\n" "\n" "Implementation specific options:\n", argv[0] ); @@ -285,6 +285,15 @@ MP_NOINLINE int main_(int argc, char **argv) { } else if (strcmp(arch, "armv7m") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7M; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; + } else if (strcmp(arch, "armv7em") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EM; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; + } else if (strcmp(arch, "armv7emsp") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EMSP; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; + } else if (strcmp(arch, "armv7emdp") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EMDP; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; } else if (strcmp(arch, "xtensa") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSA; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSA; From 40cc7ec677e962c47db567479e42c27ed8911ff6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 29 Nov 2019 12:57:07 +1100 Subject: [PATCH 0741/1299] stm32/mpconfigport.h: Use IRQ_PRI_PENDSV to protect bluetooth ringbuf. The default protection for the BLE ringbuf is to use MICROPY_BEGIN_ATOMIC_SECTION, which disables all interrupts. On stm32 it only needs to disable the lowest priority IRQ, pendsv, because that's the IRQ level at which the BLE stack is driven. --- extmod/modbluetooth.c | 1 + ports/stm32/mpconfigport.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 96cd41ae4566e..2293e03673757 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -33,6 +33,7 @@ #include "py/objarray.h" #include "py/qstr.h" #include "py/runtime.h" +#include "py/mphal.h" #include "extmod/modbluetooth.h" #include diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index fc54026f6b720..becde2b919c0e 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -366,6 +366,10 @@ static inline mp_uint_t disable_irq(void) { #define MICROPY_PY_LWIP_REENTER irq_state = raise_irq_pri(IRQ_PRI_PENDSV); #define MICROPY_PY_LWIP_EXIT restore_irq_pri(irq_state); +// Bluetooth calls must run at a raised IRQ priority +#define MICROPY_PY_BLUETOOTH_ENTER MICROPY_PY_LWIP_ENTER +#define MICROPY_PY_BLUETOOTH_EXIT MICROPY_PY_LWIP_EXIT + // We need an implementation of the log2 function which is not a macro #define MP_NEED_LOG2 (1) From 90c524c1141ed9ad8fa882dba6f36199a7768e32 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 4 Dec 2019 15:02:54 +1100 Subject: [PATCH 0742/1299] docs: Remove spaces on lines that are empty. --- docs/esp32/quickref.rst | 4 ++-- docs/esp8266/tutorial/network_tcp.rst | 2 +- docs/library/lcd160cr.rst | 2 +- docs/library/machine.RTC.rst | 2 +- docs/library/machine.TimerWiPy.rst | 6 +++--- docs/library/pyb.ADC.rst | 2 +- docs/library/pyb.Accel.rst | 2 +- docs/library/pyb.CAN.rst | 2 +- docs/library/pyb.ExtInt.rst | 2 +- docs/library/pyb.LCD.rst | 8 ++++---- docs/library/pyb.LED.rst | 2 +- docs/library/pyb.RTC.rst | 6 +++--- docs/library/pyb.Timer.rst | 4 ++-- docs/library/pyb.USB_HID.rst | 4 ++-- docs/library/pyb.USB_VCP.rst | 8 ++++---- docs/library/pyb.rst | 12 ++++++------ docs/pyboard/quickref.rst | 2 +- docs/pyboard/tutorial/amp_skin.rst | 2 +- docs/pyboard/tutorial/fading_led.rst | 18 +++++++++--------- docs/pyboard/tutorial/leds.rst | 2 +- docs/pyboard/tutorial/repl.rst | 4 ++-- docs/reference/asm_thumb2_float.rst | 4 ++-- docs/wipy/quickref.rst | 4 ++-- docs/wipy/tutorial/repl.rst | 2 +- 24 files changed, 53 insertions(+), 53 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 20e728d1c7d89..ef9b0a2e8c4aa 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -359,10 +359,10 @@ Notes: To further reduce power consumption it is possible to disable the internal pullups:: p1 = Pin(4, Pin.IN, Pin.PULL_HOLD) - + After leaving deepsleep it may be necessary to un-hold the pin explicitly (e.g. if it is an output pin) via:: - + p1 = Pin(4, Pin.OUT, None) OneWire driver diff --git a/docs/esp8266/tutorial/network_tcp.rst b/docs/esp8266/tutorial/network_tcp.rst index 852fc82f3978e..d479f62e6ab87 100644 --- a/docs/esp8266/tutorial/network_tcp.rst +++ b/docs/esp8266/tutorial/network_tcp.rst @@ -44,7 +44,7 @@ Now that we are connected we can download and display the data:: ... data = s.recv(500) ... print(str(data, 'utf8'), end='') ... - + When this loop executes it should start showing the animation (use ctrl-C to interrupt it). diff --git a/docs/library/lcd160cr.rst b/docs/library/lcd160cr.rst index bb8e6da22ce5e..e31ed94651ca5 100644 --- a/docs/library/lcd160cr.rst +++ b/docs/library/lcd160cr.rst @@ -340,7 +340,7 @@ Advanced commands .. method:: LCD160CR.set_scroll_win_param(win, param, value) Set a single parameter of a scrolling window region: - + - *win* is the window id, 0..8. - *param* is the parameter number to configure, 0..7, and corresponds to the parameters in the `set_scroll_win` method. diff --git a/docs/library/machine.RTC.rst b/docs/library/machine.RTC.rst index 95fa2b4ce6094..548ad007e0dc3 100644 --- a/docs/library/machine.RTC.rst +++ b/docs/library/machine.RTC.rst @@ -27,7 +27,7 @@ Methods .. method:: RTC.init(datetime) Initialise the RTC. Datetime is a tuple of the form: - + ``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])`` .. method:: RTC.now() diff --git a/docs/library/machine.TimerWiPy.rst b/docs/library/machine.TimerWiPy.rst index abbcc28ff7ce8..904a958c69b16 100644 --- a/docs/library/machine.TimerWiPy.rst +++ b/docs/library/machine.TimerWiPy.rst @@ -47,9 +47,9 @@ Methods tim.init(Timer.ONE_SHOT, width=32) # one shot 32-bit timer Keyword arguments: - + - ``mode`` can be one of: - + - ``TimerWiPy.ONE_SHOT`` - The timer runs once until the configured period of the channel expires. - ``TimerWiPy.PERIODIC`` - The timer runs periodically at the configured @@ -70,7 +70,7 @@ Methods object is returned (or ``None`` if there is no previous channel). Otherwise, a TimerChannel object is initialized and returned. - + The operating mode is is the one configured to the Timer object that was used to create the channel. diff --git a/docs/library/pyb.ADC.rst b/docs/library/pyb.ADC.rst index a95f2d537c33f..1b16e0c2fcccb 100644 --- a/docs/library/pyb.ADC.rst +++ b/docs/library/pyb.ADC.rst @@ -19,7 +19,7 @@ Usage:: val = adc.read_core_vref() # read MCU VREF val = adc.read_vref() # read MCU supply voltage - + Constructors ------------ diff --git a/docs/library/pyb.Accel.rst b/docs/library/pyb.Accel.rst index 9ade5c5c81523..d5c0ca8634598 100644 --- a/docs/library/pyb.Accel.rst +++ b/docs/library/pyb.Accel.rst @@ -19,7 +19,7 @@ Constructors .. class:: pyb.Accel() Create and return an accelerometer object. - + Methods ------- diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst index 09b97a187c696..ba935abfd5c4e 100644 --- a/docs/library/pyb.CAN.rst +++ b/docs/library/pyb.CAN.rst @@ -92,7 +92,7 @@ Methods Force a software restart of the CAN controller without resetting its configuration. - + If the controller enters the bus-off state then it will no longer participate in bus activity. If the controller is not configured to automatically restart (see :meth:`~CAN.init()`) then this method can be used to trigger a restart, diff --git a/docs/library/pyb.ExtInt.rst b/docs/library/pyb.ExtInt.rst index 814217cef0863..7741cc51e2381 100644 --- a/docs/library/pyb.ExtInt.rst +++ b/docs/library/pyb.ExtInt.rst @@ -54,7 +54,7 @@ Constructors .. class:: pyb.ExtInt(pin, mode, pull, callback) Create an ExtInt object: - + - ``pin`` is the pin on which to enable the interrupt (can be a pin object or any valid pin name). - ``mode`` can be one of: - ``ExtInt.IRQ_RISING`` - trigger on a rising edge; diff --git a/docs/library/pyb.LCD.rst b/docs/library/pyb.LCD.rst index 5ab127edcda0e..018902ca6896a 100644 --- a/docs/library/pyb.LCD.rst +++ b/docs/library/pyb.LCD.rst @@ -63,13 +63,13 @@ Methods .. method:: LCD.fill(colour) Fill the screen with the given colour (0 or 1 for white or black). - + This method writes to the hidden buffer. Use ``show()`` to show the buffer. .. method:: LCD.get(x, y) Get the pixel at the position ``(x, y)``. Returns 0 or 1. - + This method reads from the visible buffer. .. method:: LCD.light(value) @@ -79,7 +79,7 @@ Methods .. method:: LCD.pixel(x, y, colour) Set the pixel at ``(x, y)`` to the given colour (0 or 1). - + This method writes to the hidden buffer. Use ``show()`` to show the buffer. .. method:: LCD.show() @@ -89,7 +89,7 @@ Methods .. method:: LCD.text(str, x, y, colour) Draw the given text to the position ``(x, y)`` using the given colour (0 or 1). - + This method writes to the hidden buffer. Use ``show()`` to show the buffer. .. method:: LCD.write(str) diff --git a/docs/library/pyb.LED.rst b/docs/library/pyb.LED.rst index 1ab73a69c9aa0..d3ab965e7e7c8 100644 --- a/docs/library/pyb.LED.rst +++ b/docs/library/pyb.LED.rst @@ -13,7 +13,7 @@ Constructors .. class:: pyb.LED(id) Create an LED object associated with the given LED: - + - ``id`` is the LED number, 1-4. diff --git a/docs/library/pyb.RTC.rst b/docs/library/pyb.RTC.rst index 286268655e686..4c736597cf8db 100644 --- a/docs/library/pyb.RTC.rst +++ b/docs/library/pyb.RTC.rst @@ -28,13 +28,13 @@ Methods .. method:: RTC.datetime([datetimetuple]) Get or set the date and time of the RTC. - + With no arguments, this method returns an 8-tuple with the current date and time. With 1 argument (being an 8-tuple) it sets the date and time (and ``subseconds`` is reset to 255). - + The 8-tuple has the following format: - + (year, month, day, weekday, hours, minutes, seconds, subseconds) ``weekday`` is 1-7 for Monday through Sunday. diff --git a/docs/library/pyb.Timer.rst b/docs/library/pyb.Timer.rst index 977ba8890d7de..bb7e7e52d5648 100644 --- a/docs/library/pyb.Timer.rst +++ b/docs/library/pyb.Timer.rst @@ -112,7 +112,7 @@ Methods .. method:: Timer.deinit() Deinitialises the timer. - + Disables the callback (and the associated irq). Disables any channel callbacks (and the associated irq). @@ -191,7 +191,7 @@ Methods - Read the encoder value using the timer.counter() method. - Only works on CH1 and CH2 (and not on CH1N or CH2N) - The channel number is ignored when setting the encoder mode. - + PWM Example:: timer = pyb.Timer(2, freq=1000) diff --git a/docs/library/pyb.USB_HID.rst b/docs/library/pyb.USB_HID.rst index 70270443548d9..649dc3df4a605 100644 --- a/docs/library/pyb.USB_HID.rst +++ b/docs/library/pyb.USB_HID.rst @@ -24,11 +24,11 @@ Methods .. method:: USB_HID.recv(data, \*, timeout=5000) Receive data on the bus: - + - ``data`` can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with received bytes. - ``timeout`` is the timeout in milliseconds to wait for the receive. - + Return value: if ``data`` is an integer then a new buffer of the bytes received, otherwise the number of bytes read into ``data`` is returned. diff --git a/docs/library/pyb.USB_VCP.rst b/docs/library/pyb.USB_VCP.rst index 94ea41848593d..b16924cf60b2e 100644 --- a/docs/library/pyb.USB_VCP.rst +++ b/docs/library/pyb.USB_VCP.rst @@ -92,21 +92,21 @@ Methods .. method:: USB_VCP.recv(data, \*, timeout=5000) Receive data on the bus: - + - ``data`` can be an integer, which is the number of bytes to receive, or a mutable buffer, which will be filled with received bytes. - ``timeout`` is the timeout in milliseconds to wait for the receive. - + Return value: if ``data`` is an integer then a new buffer of the bytes received, otherwise the number of bytes read into ``data`` is returned. .. method:: USB_VCP.send(data, \*, timeout=5000) Send data over the USB VCP: - + - ``data`` is the data to send (an integer to send, or a buffer object). - ``timeout`` is the timeout in milliseconds to wait for the send. - + Return value: number of bytes sent. diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst index 9ba7e991e5190..714207ba15c4f 100644 --- a/docs/library/pyb.rst +++ b/docs/library/pyb.rst @@ -20,7 +20,7 @@ Time related functions .. function:: millis() Returns the number of milliseconds since the board was last reset. - + The result is always a MicroPython smallint (31-bit signed number), so after 2^30 milliseconds (about 12.4 days) this will start to return negative numbers. @@ -32,7 +32,7 @@ Time related functions .. function:: micros() Returns the number of microseconds since the board was last reset. - + The result is always a MicroPython smallint (31-bit signed number), so after 2^30 microseconds (about 17.8 minutes) this will start to return negative numbers. @@ -44,10 +44,10 @@ Time related functions .. function:: elapsed_millis(start) Returns the number of milliseconds which have elapsed since ``start``. - + This function takes care of counter wrap, and always returns a positive number. This means it can be used to measure periods up to about 12.4 days. - + Example:: start = pyb.millis() @@ -57,10 +57,10 @@ Time related functions .. function:: elapsed_micros(start) Returns the number of microseconds which have elapsed since ``start``. - + This function takes care of counter wrap, and always returns a positive number. This means it can be used to measure periods up to about 17.8 minutes. - + Example:: start = pyb.micros() diff --git a/docs/pyboard/quickref.rst b/docs/pyboard/quickref.rst index b1195ce7c86fb..3dbd0930436f4 100644 --- a/docs/pyboard/quickref.rst +++ b/docs/pyboard/quickref.rst @@ -66,7 +66,7 @@ See :ref:`pyb.LED `. :: led.toggle() led.on() led.off() - + # LEDs 3 and 4 support PWM intensity (0-255) LED(4).intensity() # get intensity LED(4).intensity(128) # set intensity to half diff --git a/docs/pyboard/tutorial/amp_skin.rst b/docs/pyboard/tutorial/amp_skin.rst index 697637f9d2b31..bcb583261381c 100644 --- a/docs/pyboard/tutorial/amp_skin.rst +++ b/docs/pyboard/tutorial/amp_skin.rst @@ -60,7 +60,7 @@ on your pyboard (either on the flash or the SD card in the top-level directory). or to convert any file you have with the command:: avconv -i original.wav -ar 22050 -codec pcm_u8 test.wav - + Then you can do:: >>> import wave diff --git a/docs/pyboard/tutorial/fading_led.rst b/docs/pyboard/tutorial/fading_led.rst index 8303c96030ddf..79648bee1ad41 100644 --- a/docs/pyboard/tutorial/fading_led.rst +++ b/docs/pyboard/tutorial/fading_led.rst @@ -27,10 +27,10 @@ For this tutorial, we will use the ``X1`` pin. Connect one end of the resistor t Code ---- By examining the :ref:`pyboard_quickref`, we see that ``X1`` is connected to channel 1 of timer 5 (``TIM5 CH1``). Therefore we will first create a ``Timer`` object for timer 5, then create a ``TimerChannel`` object for channel 1:: - + from pyb import Timer from time import sleep - + # timer 5 will be created with a frequency of 100 Hz tim = pyb.Timer(5, freq=100) tchannel = tim.channel(1, Timer.PWM, pin=pyb.Pin.board.X1, pulse_width=0) @@ -47,16 +47,16 @@ To achieve the fading effect shown at the beginning of this tutorial, we want to # how much to change the pulse-width by each step wstep = 1500 cur_width = min_width - + while True: tchannel.pulse_width(cur_width) - + # this determines how often we change the pulse-width. It is # analogous to frames-per-second sleep(0.01) - + cur_width += wstep - + if cur_width > max_width: cur_width = min_width @@ -67,11 +67,11 @@ If we want to have a breathing effect, where the LED fades from dim to bright th while True: tchannel.pulse_width(cur_width) - + sleep(0.01) - + cur_width += wstep - + if cur_width > max_width: cur_width = max_width wstep *= -1 diff --git a/docs/pyboard/tutorial/leds.rst b/docs/pyboard/tutorial/leds.rst index 2b76d17cde77f..05f3b619e398e 100644 --- a/docs/pyboard/tutorial/leds.rst +++ b/docs/pyboard/tutorial/leds.rst @@ -17,7 +17,7 @@ This is all very well but we would like this process to be automated. Open the f pyb.delay(1000) When you save, the red light on the pyboard should turn on for about a second. To run the script, do a soft reset (CTRL-D). The pyboard will then restart and you should see a green light continuously flashing on and off. Success, the first step on your path to building an army of evil robots! When you are bored of the annoying flashing light then press CTRL-C at your terminal to stop it running. - + So what does this code do? First we need some terminology. Python is an object-oriented language, almost everything in python is a *class* and when you create an instance of a class you get an *object*. Classes have *methods* associated to them. A method (also called a member function) is used to interact with or control the object. The first line of code creates an LED object which we have then called led. When we create the object, it takes a single parameter which must be between 1 and 4, corresponding to the 4 LEDs on the board. The pyb.LED class has three important member functions that we will use: on(), off() and toggle(). The other function that we use is pyb.delay() this simply waits for a given time in milliseconds. Once we have created the LED object, the statement while True: creates an infinite loop which toggles the led between on and off and waits for 1 second. diff --git a/docs/pyboard/tutorial/repl.rst b/docs/pyboard/tutorial/repl.rst index 3853b1578567b..973d1846a0f0e 100644 --- a/docs/pyboard/tutorial/repl.rst +++ b/docs/pyboard/tutorial/repl.rst @@ -41,7 +41,7 @@ Mac OS X Open a terminal and run:: screen /dev/tty.usbmodem* - + When you are finished and want to exit screen, type CTRL-A CTRL-\\. Linux @@ -50,7 +50,7 @@ Linux Open a terminal and run:: screen /dev/ttyACM0 - + You can also try ``picocom`` or ``minicom`` instead of screen. You may have to use ``/dev/ttyACM1`` or a higher number for ``ttyACM``. And, you may need to give yourself the correct permissions to access this devices (eg group ``uucp`` or ``dialout``, diff --git a/docs/reference/asm_thumb2_float.rst b/docs/reference/asm_thumb2_float.rst index 4acb734eeb44c..46560413c9541 100644 --- a/docs/reference/asm_thumb2_float.rst +++ b/docs/reference/asm_thumb2_float.rst @@ -31,7 +31,7 @@ Arithmetic * vsqrt(Sd, Sm) ``Sd = sqrt(Sm)`` Registers may be identical: ``vmul(S0, S0, S0)`` will execute ``S0 = S0*S0`` - + Move between ARM core and FPU registers --------------------------------------- @@ -40,7 +40,7 @@ Move between ARM core and FPU registers The FPU has a register known as FPSCR, similar to the ARM core's APSR, which stores condition codes plus other data. The following instructions provide access to this. - + * vmrs(APSR\_nzcv, FPSCR) Move the floating-point N, Z, C, and V flags to the APSR N, Z, C, and V flags. diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst index 6349676cf7e1d..a22ea45b55149 100644 --- a/docs/wipy/quickref.rst +++ b/docs/wipy/quickref.rst @@ -62,7 +62,7 @@ Timer ``id``'s take values from 0 to 3.:: tim = Timer(0, mode=Timer.PERIODIC) tim_a = tim.channel(Timer.A, freq=1000) tim_a.freq(5) # 5 Hz - + p_out = Pin('GP2', mode=Pin.OUT) tim_a.irq(trigger=Timer.TIMEOUT, handler=lambda t: p_out.toggle()) @@ -75,7 +75,7 @@ See :ref:`machine.Pin ` and :ref:`machine.Timer `. : # timer 1 in PWM mode and width must be 16 buts tim = Timer(1, mode=Timer.PWM, width=16) - + # enable channel A @1KHz with a 50.55% duty cycle tim_a = tim.channel(Timer.A, freq=1000, duty_cycle=5055) diff --git a/docs/wipy/tutorial/repl.rst b/docs/wipy/tutorial/repl.rst index 8c60e2c1d134b..95b545d097830 100644 --- a/docs/wipy/tutorial/repl.rst +++ b/docs/wipy/tutorial/repl.rst @@ -51,7 +51,7 @@ Open a terminal and run:: or:: $ screen /dev/tty.usbmodem* 115200 - + When you are finished and want to exit ``screen``, type CTRL-A CTRL-\\. If your keyboard does not have a \\-key (i.e. you need an obscure combination for \\ like ALT-SHIFT-7) you can remap the ``quit`` command: - create ``~/.screenrc`` From d7dbd267e73bf745e985da9155490b5358cb874a Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 4 Dec 2019 10:40:16 +1100 Subject: [PATCH 0743/1299] docs/reference: Add docs describing use of pyboard.py. --- docs/reference/index.rst | 1 + docs/reference/pyboard.py.rst | 133 ++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 docs/reference/pyboard.py.rst diff --git a/docs/reference/index.rst b/docs/reference/index.rst index d0c7f69de9561..4dd52b9c83858 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -26,3 +26,4 @@ implementation and the best practices to use them. constrained.rst packages.rst asm_thumb2_index.rst + pyboard.py.rst diff --git a/docs/reference/pyboard.py.rst b/docs/reference/pyboard.py.rst new file mode 100644 index 0000000000000..60d7509afe308 --- /dev/null +++ b/docs/reference/pyboard.py.rst @@ -0,0 +1,133 @@ +.. _pyboard_py: + +The pyboard.py tool +=================== + +This is a standalone Python tool that runs on your PC that provides a way to: + +* Quickly run a Python script or command on a MicroPython device. This is useful + while developing MicroPython programs to quickly test code without needing to + copy files to/from the device. + +* Access the filesystem on a device. This allows you to deploy your code to the + device (even if the board doesn't support USB MSC). + +Despite the name, ``pyboard.py`` works on all MicroPython ports that support the +raw REPL (including STM32, ESP32, ESP8266, NRF). + +You can download the latest version from `GitHub +`_. The +only dependency is the ``pyserial`` library which can be installed from PiPy or +your system package manager. + +Running ``pyboard.py --help`` gives the following output: + +.. code-block:: text + + usage: pyboard [-h] [--device DEVICE] [-b BAUDRATE] [-u USER] + [-p PASSWORD] [-c COMMAND] [-w WAIT] [--follow] [-f] + [files [files ...]] + + Run scripts on the pyboard. + + positional arguments: + files input files + + optional arguments: + -h, --help show this help message and exit + --device DEVICE the serial device or the IP address of the + pyboard + -b BAUDRATE, --baudrate BAUDRATE + the baud rate of the serial device + -u USER, --user USER the telnet login username + -p PASSWORD, --password PASSWORD + the telnet login password + -c COMMAND, --command COMMAND + program passed in as string + -w WAIT, --wait WAIT seconds to wait for USB connected board to become + available + --follow follow the output after running the scripts + [default if no scripts given] + -f, --filesystem perform a filesystem action + +Running a command on the device +------------------------------- + +This is useful for testing short snippets of code, or to script an interaction +with the device.:: + + $ pyboard.py --device /dev/ttyACM0 -c 'print(1+1)' + 2 + +Running a script on the device +------------------------------ + +If you have a script, ``app.py`` that you want to run on a device, then use:: + + $ pyboard.py --device /dev/ttyACM0 app.py + +Note that this doesn't actually copy app.py to the device's filesystem, it just +loads the code into RAM and executes it. Any output generated by the program +will be displayed. + +If the program app.py does not finish then you'll need to stop ``pyboard.py``, +eg with Ctrl-C. The program ``app.py`` will still continue to run on the +MicroPython device. + +Filesystem access +----------------- + +Using the ``-f`` flag, the following filesystem operations are supported: + +* ``cp src [src...] dest`` Copy files to/from the device. +* ``cat path`` Print the contents of a file on the device. +* ``ls [path]`` List contents of a directory (defaults to current working directory). +* ``rm path`` Remove a file. +* ``mkdir path`` Create a directory. +* ``rmdir path`` Remove a directory. + +The ``cp`` command uses a ``ssh``-like convention for referring to local and +remote files. Any path starting with a ``:`` will be interpreted as on the +device, otherwise it will be local. So:: + + $ pyboard.py --device /dev/ttyACM0 -f cp main.py :main.py + +will copy main.py from the current directory on the PC to a file named main.py +on the device. The filename can be omitted, e.g.:: + + $ pyboard.py --device /dev/ttyACM0 -f cp main.py : + +is equivalent to the above. + +Some more examples:: + + # Copy main.py from the device to the local PC. + $ pyboard.py --device /dev/ttyACM0 -f cp :main.py main.py + # Same, but using . instead. + $ pyboard.py --device /dev/ttyACM0 -f cp :main.py . + + # Copy three files to the device, keeping their names + # and paths (note: `lib` must exist on the device) + $ pyboard.py --device /dev/ttyACM0 -f cp main.py app.py lib/foo.py : + + # Remove a file from the device. + $ pyboard.py --device /dev/ttyACM0 -f rm util.py + + # Print the contents of a file on the device. + $ pyboard.py --device /dev/ttyACM0 -f cat boot.py + ...contents of boot.py... + +Using the pyboard library +------------------------- + +You can also use ``pyboard.py`` as a library for scripting interactions with a +MicroPython board. + +.. code-block:: python + + import pyboard + pyb = pyboard.Pyboard('/dev/ttyACM0', 115200) + pyb.enter_raw_repl() + ret = pyb.exec('print(1+1)') + print(ret) + pyb.exit_raw_repl() From f2650be844d73b09b990ec2c0328e0262bb99442 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 4 Dec 2019 13:50:51 +1100 Subject: [PATCH 0744/1299] docs/library: Add docs for pyb.Flash class. --- docs/library/pyb.Flash.rst | 52 ++++++++++++++++++++++++++++++++++++++ docs/library/pyb.rst | 1 + 2 files changed, 53 insertions(+) create mode 100644 docs/library/pyb.Flash.rst diff --git a/docs/library/pyb.Flash.rst b/docs/library/pyb.Flash.rst new file mode 100644 index 0000000000000..2d2f83da1c6ad --- /dev/null +++ b/docs/library/pyb.Flash.rst @@ -0,0 +1,52 @@ +.. currentmodule:: pyb +.. _pyb.Flash: + +class Flash -- access to built-in flash storage +=============================================== + +The Flash class allows direct access to the primary flash device on the pyboard. + +In most cases, to store persistent data on the device, you'll want to use a +higher-level abstraction, for example the filesystem via Python's standard file +API, but this interface is useful to :ref:`customise the filesystem +configuration ` or implement a low-level storage system for your +application. + +Constructors +------------ + +.. class:: pyb.Flash() + + Create and return a block device that represents the flash device presented + to the USB mass storage interface. + + It includes a virtual partition table at the start, and the actual flash + starts at block ``0x100``. + + This constructor is deprecated and will be removed in a future version of MicroPython. + +.. class:: pyb.Flash(\*, start=-1, len=-1) + + Create and return a block device that accesses the flash at the specified offset. The length defaults to the remaining size of the device. + + The *start* and *len* offsets are in bytes, and must be a multiple of the block size (typically 512 for internal flash). + +Methods +------- + +.. method:: Flash.readblocks(block_num, buf) +.. method:: Flash.readblocks(block_num, buf, offset) +.. method:: Flash.writeblocks(block_num, buf) +.. method:: Flash.writeblocks(block_num, buf, offset) +.. method:: Flash.ioctl(cmd, arg) + + These methods implement the simple and :ref:`extended + ` block protocol defined by + :class:`uos.AbstractBlockDev`. + +Hardware Note +------------- + +On boards with external spiflash (e.g. Pyboard D), the MicroPython firmware will +be configured to use that as the primary flash storage. On all other boards, the +internal flash inside the :term:`MCU` will be used. diff --git a/docs/library/pyb.rst b/docs/library/pyb.rst index 714207ba15c4f..34103195ddd1c 100644 --- a/docs/library/pyb.rst +++ b/docs/library/pyb.rst @@ -309,6 +309,7 @@ Classes pyb.CAN.rst pyb.DAC.rst pyb.ExtInt.rst + pyb.Flash.rst pyb.I2C.rst pyb.LCD.rst pyb.LED.rst From 9a849cc7caee63560ecd2455a29615a44e2c809f Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 4 Dec 2019 10:42:07 +1100 Subject: [PATCH 0745/1299] docs: Add littlefs docs and a filesystem tutorial. --- docs/library/esp32.rst | 6 +- docs/library/uos.rst | 100 +++++------- docs/reference/filesystem.rst | 278 ++++++++++++++++++++++++++++++++++ docs/reference/index.rst | 1 + 4 files changed, 322 insertions(+), 63 deletions(-) create mode 100644 docs/reference/filesystem.rst diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index a593965ae2740..68379624e69b5 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -56,10 +56,14 @@ This class gives access to the partitions in the device's flash memory. Returns a 6-tuple ``(type, subtype, addr, size, label, encrypted)``. .. method:: Partition.readblocks(block_num, buf) +.. method:: Partition.readblocks(block_num, buf, offset) .. method:: Partition.writeblocks(block_num, buf) +.. method:: Partition.writeblocks(block_num, buf, offset) .. method:: Partition.ioctl(cmd, arg) - These methods implement the block protocol defined by :class:`uos.AbstractBlockDev`. + These methods implement the simple and :ref:`extended + ` block protocol defined by + :class:`uos.AbstractBlockDev`. .. method:: Partition.set_boot() diff --git a/docs/library/uos.rst b/docs/library/uos.rst index d8d8b7a972eeb..84d341ac210ac 100644 --- a/docs/library/uos.rst +++ b/docs/library/uos.rst @@ -178,6 +178,35 @@ represented by VFS classes. Build a FAT filesystem on *block_dev*. +.. class:: VfsLfs1(block_dev) + + Create a filesystem object that uses the `littlefs v1 filesystem format`_. + Storage of the littlefs filesystem is provided by *block_dev*, which must + support the :ref:`extended interface `. + Objects created by this constructor can be mounted using :func:`mount`. + + See :ref:`filesystem` for more information. + + .. staticmethod:: mkfs(block_dev) + + Build a Lfs1 filesystem on *block_dev*. + +.. class:: VfsLfs2(block_dev) + + Create a filesystem object that uses the `littlefs v2 filesystem format`_. + Storage of the littlefs filesystem is provided by *block_dev*, which must + support the :ref:`extended interface `. + Objects created by this constructor can be mounted using :func:`mount`. + + See :ref:`filesystem` for more information. + + .. staticmethod:: mkfs(block_dev) + + Build a Lfs2 filesystem on *block_dev*. + +.. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1 +.. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs + Block devices ------------- @@ -187,9 +216,15 @@ implementation of this class will usually allow access to the memory-like functionality a piece of hardware (like flash memory). A block device can be used by a particular filesystem driver to store the data for its filesystem. +.. _block-device-interface: + +Simple and extended interface +............................. + There are two compatible signatures for the ``readblocks`` and ``writeblocks`` methods (see below), in order to support a variety of use cases. A given block -device may implement one form or the other, or both at the same time. +device may implement one form or the other, or both at the same time. The second +form (with the offset parameter) is referred to as the "extended interface". .. class:: AbstractBlockDev(...) @@ -247,64 +282,5 @@ device may implement one form or the other, or both at the same time. (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase -By way of example, the following class will implement a block device that stores -its data in RAM using a ``bytearray``:: - - class RAMBlockDev: - def __init__(self, block_size, num_blocks): - self.block_size = block_size - self.data = bytearray(block_size * num_blocks) - - def readblocks(self, block_num, buf): - for i in range(len(buf)): - buf[i] = self.data[block_num * self.block_size + i] - - def writeblocks(self, block_num, buf): - for i in range(len(buf)): - self.data[block_num * self.block_size + i] = buf[i] - - def ioctl(self, op, arg): - if op == 4: # get number of blocks - return len(self.data) // self.block_size - if op == 5: # get block size - return self.block_size - -It can be used as follows:: - - import uos - - bdev = RAMBlockDev(512, 50) - uos.VfsFat.mkfs(bdev) - vfs = uos.VfsFat(bdev) - uos.mount(vfs, '/ramdisk') - -An example of a block device that supports both signatures and behaviours of -the :meth:`readblocks` and :meth:`writeblocks` methods is:: - - class RAMBlockDev: - def __init__(self, block_size, num_blocks): - self.block_size = block_size - self.data = bytearray(block_size * num_blocks) - - def readblocks(self, block, buf, offset=0): - addr = block_num * self.block_size + offset - for i in range(len(buf)): - buf[i] = self.data[addr + i] - - def writeblocks(self, block_num, buf, offset=None): - if offset is None: - # do erase, then write - for i in range(len(buf) // self.block_size): - self.ioctl(6, block_num + i) - offset = 0 - addr = block_num * self.block_size + offset - for i in range(len(buf)): - self.data[addr + i] = buf[i] - - def ioctl(self, op, arg): - if op == 4: # block count - return len(self.data) // self.block_size - if op == 5: # block size - return self.block_size - if op == 6: # block erase - return 0 +See :ref:`filesystem` for example implementations of block devices using both +protocols. diff --git a/docs/reference/filesystem.rst b/docs/reference/filesystem.rst new file mode 100644 index 0000000000000..71d34e795407a --- /dev/null +++ b/docs/reference/filesystem.rst @@ -0,0 +1,278 @@ +.. _filesystem: + +Working with filesystems +======================== + +.. contents:: + +This tutorial describes how MicroPython provides an on-device filesystem, +allowing standard Python file I/O methods to be used with persistent storage. + +MicroPython automatically creates a default configuration and auto-detects the +primary filesystem, so this tutorial will be mostly useful if you want to modify +the partitioning, filesystem type, or use custom block devices. + +The filesystem is typically backed by internal flash memory on the device, but +can also use external flash, RAM, or a custom block device. + +On some ports (e.g. STM32), the filesystem may also be available over USB MSC to +a host PC. :ref:`pyboard_py` also provides a way for the host PC to access to +the filesystem on all ports. + +Note: This is mainly for use on bare-metal ports like STM32 and ESP32. On ports +with an operating system (e.g. the Unix port) the filesystem is provided by the +host OS. + +VFS +--- + +MicroPython implements a Unix-like Virtual File System (VFS) layer. All mounted +filesystems are combined into a single virtual filesystem, starting at the root +``/``. Filesystems are mounted into directories in this structure, and at +startup the working directory is changed to where the primary filesystem is +mounted. + +On STM32 / Pyboard, the internal flash is mounted at ``/flash``, and optionally +the SDCard at ``/sd``. On ESP8266/ESP32, the primary filesystem is mounted at +``/``. + +Block devices +------------- + +A block device is an instance of a class that implements the +:class:`uos.AbstractBlockDev` protocol. + +Built-in block devices +~~~~~~~~~~~~~~~~~~~~~~ + +Ports provide built-in block devices to access their primary flash. + +On power-on, MicroPython will attempt to detect the filesystem on the default +flash and configure and mount it automatically. If no filesystem is found, +MicroPython will attempt to create a FAT filesystem spanning the entire flash. +Ports can also provide a mechanism to "factory reset" the primary flash, usually +by some combination of button presses at power on. + +STM32 / Pyboard +............... + +The :ref:`pyb.Flash ` class provides access to the internal flash. On some +boards which have larger external flash (e.g. Pyboard D), it will use that +instead. The ``start`` kwarg should always be specified, i.e. +``pyb.Flash(start=0)``. + +Note: For backwards compatibility, when constructed with no arguments (i.e. +``pyb.Flash()``), it only implements the simple block interface and reflects the +virtual device presented to USB MSC (i.e. it includes a virtual partition table +at the start). + +ESP8266 +....... + +The internal flash is exposed as a block device object which is created in the +``flashbdev`` module on start up. This object is by default added as a global +variable so it can usually be accessed simply as ``bdev``. This implements the +extended interface. + +ESP32 +..... + +The :class:`esp32.Partition` class implements a block device for partitions +defined for the board. Like ESP8266, there is a global variable ``bdev`` which +points to the default partition. This implements the extended interface. + +Custom block devices +~~~~~~~~~~~~~~~~~~~~ + +The following class implements a simple block device that stores its data in +RAM using a ``bytearray``:: + + class RAMBlockDev: + def __init__(self, block_size, num_blocks): + self.block_size = block_size + self.data = bytearray(block_size * num_blocks) + + def readblocks(self, block_num, buf): + for i in range(len(buf)): + buf[i] = self.data[block_num * self.block_size + i] + + def writeblocks(self, block_num, buf): + for i in range(len(buf)): + self.data[block_num * self.block_size + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # get number of blocks + return len(self.data) // self.block_size + if op == 5: # get block size + return self.block_size + +It can be used as follows:: + + import os + + bdev = RAMBlockDev(512, 50) + os.VfsFat.mkfs(bdev) + os.mount(bdev, '/ramdisk') + +An example of a block device that supports both the simple and extended +interface (i.e. both signatures and behaviours of the +:meth:`uos.AbstractBlockDev.readblocks` and +:meth:`uos.AbstractBlockDev.writeblocks` methods) is:: + + class RAMBlockDev: + def __init__(self, block_size, num_blocks): + self.block_size = block_size + self.data = bytearray(block_size * num_blocks) + + def readblocks(self, block, buf, offset=0): + addr = block_num * self.block_size + offset + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block_num, buf, offset=None): + if offset is None: + # do erase, then write + for i in range(len(buf) // self.block_size): + self.ioctl(6, block_num + i) + offset = 0 + addr = block_num * self.block_size + offset + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.block_size + if op == 5: # block size + return self.block_size + if op == 6: # block erase + return 0 + +As it supports the extended interface, it can be used with :class:`littlefs +`:: + + import os + + bdev = RAMBlockDev(512, 50) + os.VfsLfs2.mkfs(bdev) + os.mount(bdev, '/ramdisk') + +Filesystems +----------- + +MicroPython ports can provide implementations of :class:`FAT `, +:class:`littlefs v1 ` and :class:`littlefs v2 `. + +The following table shows which filesystems are included in the firmware by +default for given port/board combinations, however they can be optionally +enabled in a custom firmware build. + +==================== ===== =========== =========== +Board FAT littlefs v1 littlefs v2 +==================== ===== =========== =========== +pyboard 1.0, 1.1, D Yes No Yes +Other STM32 Yes No No +ESP8266 Yes No No +ESP32 Yes No Yes +==================== ===== =========== =========== + +FAT +~~~ + +The main advantage of the FAT filesystem is that it can be accessed over USB MSC +on supported boards (e.g. STM32) without any additional drivers required on the +host PC. + +However, FAT is not tolerant to power failure during writes and this can lead to +filesystem corruption. For applications that do not require USB MSC, it is +recommended to use littlefs instead. + +To format the entire flash using FAT:: + + # ESP8266 and ESP32 + import os + os.umount('/') + os.VfsFat.mkfs(bdev) + os.mount(bdev, '/') + + # STM32 + import os, pyb + os.umount('/flash') + os.VfsFat.mkfs(pyb.Flash(start=0)) + os.mount(pyb.Flash(start=0), '/flash') + os.chdir('/flash') + +Littlefs +~~~~~~~~ + +Littlefs_ is a filesystem designed for flash-based devices, and is much more +resistant to filesystem corruption. + +Note: It can be still be accessed over USB MSC using the `littlefs FUSE +driver`_. Note that you must use the ``-b=4096`` option to override the block +size. + +.. _littlefs FUSE driver: https://github.com/ARMmbed/littlefs-fuse/tree/master/littlefs + +.. _Littlefs: https://github.com/ARMmbed/littlefs + +To format the entire flash using littlefs v2:: + + # ESP8266 and ESP32 + import os + os.umount('/') + os.VfsLfs2.mkfs(bdev) + os.mount(bdev, '/') + + # STM32 + import os, pyb + os.umount('/flash') + os.VfsLfs2.mkfs(pyb.Flash(start=0)) + os.mount(pyb.Flash(start=0), '/flash') + os.chdir('/flash') + +Hybrid (STM32) +~~~~~~~~~~~~~~ + +By using the ``start`` and ``len`` kwargs to :class:`pyb.Flash`, you can create +block devices spanning a subset of the flash device. + +For example, to configure the first 256kiB as FAT (and available over USB MSC), +and the remainder as littlefs:: + + import os, pyb + os.umount('/flash') + p1 = pyb.Flash(start=0, len=256*1024) + p2 = pyb.Flash(start=256*1024) + os.VfsFat.mkfs(p1) + os.VfsLfs2.mkfs(p2) + os.mount(p1, '/flash') + os.mount(p2, '/data') + os.chdir('/flash') + +This might be useful to make your Python files, configuration and other +rarely-modified content available over USB MSC, but allowing for frequently +changing application data to reside on littlefs with better resilience to power +failure, etc. + +The partition at offset ``0`` will be mounted automatically (and the filesystem +type automatically detected), but you can add:: + + import os, pyb + p2 = pyb.Flash(start=256*1024) + os.mount(p2, '/data') + +to ``boot.py`` to mount the data partition. + +Hybrid (ESP32) +~~~~~~~~~~~~~~ + +On ESP32, if you build custom firmware, you can modify ``partitions.csv`` to +define an arbitrary partition layout. + +At boot, the partition named "vfs" will be mounted at ``/`` by default, but any +additional partitions can be mounted in your ``boot.py`` using:: + + import esp32, os + p = esp32.Partition.find(esp32.Partition.TYPE_DATA, label='foo') + os.mount(p, '/foo') + diff --git a/docs/reference/index.rst b/docs/reference/index.rst index 4dd52b9c83858..1eaaa85c856f1 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -26,4 +26,5 @@ implementation and the best practices to use them. constrained.rst packages.rst asm_thumb2_index.rst + filesystem.rst pyboard.py.rst From 7aeafe2ae9f16af74d22604b3090641a664b2da2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 29 Nov 2019 12:48:38 +1100 Subject: [PATCH 0746/1299] extmod/modbluetooth: Add optional 4th arg to gattc_write for write mode. This allows the user to explicitly select the behaviour of the write to the remote peripheral. This is needed for peripherals that have characteristics with WRITE_NO_RESPONSE set (instead of normal WRITE). The function's signature is now: BLE.gattc_write(conn_handle, value_handle, data, mode=0) mode=0 means write without response, while mode=1 means write with response. The latter was the original behaviour so this commit is a change in behaviour of this method, and one should specify 1 as the 4th argument to get back the old behaviour. In the future there could be more modes supported, such as long writes. --- docs/library/ubluetooth.rst | 15 +++++++++++++-- extmod/modbluetooth.c | 8 ++++++-- extmod/modbluetooth.h | 6 +++++- extmod/modbluetooth_nimble.c | 11 +++++++++-- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index 2d3af1bb6b0d5..fd4c012d29d15 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -310,12 +310,23 @@ Central Role (GATT Client) On success, the ``_IRQ_GATTC_READ_RESULT`` event will be raised. -.. method:: BLE.gattc_write(conn_handle, value_handle, data) +.. method:: BLE.gattc_write(conn_handle, value_handle, data, mode=0) Issue a remote write to a connected peripheral for the specified characteristic or descriptor handle. - On success, the ``_IRQ_GATTC_WRITE_STATUS`` event will be raised. + The argument *mode* specifies the write behaviour, with the currently + supported values being: + + * ``mode=0`` (default) is a write-without-response: the write will + be sent to the remote peripheral but no confirmation will be + returned, and no event will be raised. + * ``mode=1`` is a write-with-response: the remote peripheral is + requested to send a response/acknowledgement that it received the + data. + + If a response is received from the remote peripheral the + ``_IRQ_GATTC_WRITE_STATUS`` event will be raised. class UUID diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 2293e03673757..74f73c1f2bce3 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -641,9 +641,13 @@ STATIC mp_obj_t bluetooth_ble_gattc_write(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo = {0}; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); size_t len = bufinfo.len; - return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, &len)); + unsigned int mode = MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE; + if (n_args == 5) { + mode = mp_obj_get_int(args[4]); + } + return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, &len, mode)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_write_obj, 4, 4, bluetooth_ble_gattc_write); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_write_obj, 4, 5, bluetooth_ble_gattc_write); #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 8a3ab414fdcb9..fbae67bc4546b 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -65,6 +65,10 @@ #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (1 << 3) #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (1 << 4) +// For mp_bluetooth_gattc_write, the mode parameter +#define MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE (0) +#define MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE (1) + // Type value also doubles as length. #define MP_BLUETOOTH_UUID_TYPE_16 (2) #define MP_BLUETOOTH_UUID_TYPE_32 (4) @@ -219,7 +223,7 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle); // Write the value to the remote peripheral. -int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len); +int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode); #endif ///////////////////////////////////////////////////////////////////////////// diff --git a/extmod/modbluetooth_nimble.c b/extmod/modbluetooth_nimble.c index 83eb4b88a64a0..930dd06d1103e 100644 --- a/extmod/modbluetooth_nimble.c +++ b/extmod/modbluetooth_nimble.c @@ -816,8 +816,15 @@ STATIC int ble_gatt_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_er } // Write the value to the remote peripheral. -int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len) { - int err = ble_gattc_write_flat(conn_handle, value_handle, value, *value_len, &ble_gatt_attr_write_cb, NULL); +int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) { + int err; + if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) { + err = ble_gattc_write_no_rsp_flat(conn_handle, value_handle, value, *value_len); + } else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) { + err = ble_gattc_write_flat(conn_handle, value_handle, value, *value_len, &ble_gatt_attr_write_cb, NULL); + } else { + err = BLE_HS_EINVAL; + } return ble_hs_err_to_errno(err); } From 84958a8fe14781d5f678f2d6310cbd324779f50c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 29 Nov 2019 15:26:57 +1100 Subject: [PATCH 0747/1299] extmod/modbluetooth: Allow setting ringbuf size via BLE.config(rxbuf=). The size of the event ringbuf was previously fixed to compile-time config value, but it's necessary to sometimes increase this for applications that have large characteristic buffers to read, or many events at once. With this commit the size can be set via BLE.config(rxbuf=512), for example. This also resizes the internal event data buffer which sets the maximum size of incoming data passed to the event handler. --- docs/library/ubluetooth.rst | 17 ++++++- extmod/modbluetooth.c | 96 +++++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 17 deletions(-) diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index fd4c012d29d15..ddcd28d9e6719 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -32,14 +32,27 @@ Configuration The radio must be made active before using any other methods on this class. -.. method:: BLE.config(name) +.. method:: BLE.config('param') + BLE.config(param=value, ...) - Queries a configuration value by *name*. Currently supported values are: + Get or set configuration values of the BLE interface. To get a value the + parameter name should be quoted as a string, and just one parameter is + queried at a time. To set values use the keyword syntax, and one ore more + parameter can be set at a time. + + Currently supported values are: - ``'mac'``: Returns the device MAC address. If a device has a fixed address (e.g. PYBD) then it will be returned. Otherwise (e.g. ESP32) a random address will be generated when the BLE interface is made active. + - ``'rxbuf'``: Set the size in bytes of the internal buffer used to store + incoming events. This buffer is global to the entire BLE driver and so + handles incoming data for all events, including all characteristics. + Increasing this allows better handling of bursty incoming data (for + example scan results) and the ability for a central role to receive + larger characteristic values. + Event Handling -------------- diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 74f73c1f2bce3..756d3d6d1cd30 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -46,7 +46,10 @@ #define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000 #define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5 -#define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN (MICROPY_PY_BLUETOOTH_RINGBUF_SIZE / 2) + +// This formula is intended to allow queuing the data of a large characteristic +// while still leaving room for a couple of normal (small, fixed size) events. +#define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(ringbuf_size) (MAX((int)((ringbuf_size) / 2), (int)(ringbuf_size) - 64)) STATIC const mp_obj_type_t bluetooth_ble_type; STATIC const mp_obj_type_t bluetooth_uuid_type; @@ -58,7 +61,8 @@ typedef struct { bool irq_scheduled; mp_obj_t irq_data_tuple; uint8_t irq_data_addr_bytes[6]; - uint8_t irq_data_data_bytes[MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN]; + uint16_t irq_data_data_alloc; + uint8_t *irq_data_data_bytes; mp_obj_str_t irq_data_addr; mp_obj_str_t irq_data_data; mp_obj_bluetooth_uuid_t irq_data_uuid; @@ -244,11 +248,12 @@ STATIC mp_obj_t bluetooth_ble_make_new(const mp_obj_type_t *type, size_t n_args, // Pre-allocated buffers for address, payload and uuid. o->irq_data_addr.base.type = &mp_type_bytes; o->irq_data_addr.data = o->irq_data_addr_bytes; + o->irq_data_data_alloc = MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); o->irq_data_data.base.type = &mp_type_bytes; - o->irq_data_data.data = o->irq_data_data_bytes; + o->irq_data_data.data = m_new(uint8_t, o->irq_data_data_alloc); o->irq_data_uuid.base.type = &bluetooth_uuid_type; - // Allocate the ringbuf. TODO: Consider making the size user-specified. + // Allocate the default ringbuf. ringbuf_alloc(&o->ringbuf, MICROPY_PY_BLUETOOTH_RINGBUF_SIZE); MP_STATE_VM(bluetooth) = MP_OBJ_FROM_PTR(o); @@ -273,16 +278,77 @@ STATIC mp_obj_t bluetooth_ble_active(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_active_obj, 1, 2, bluetooth_ble_active); -STATIC mp_obj_t bluetooth_ble_config(mp_obj_t self_in, mp_obj_t param) { - if (param == MP_OBJ_NEW_QSTR(MP_QSTR_mac)) { - uint8_t addr[6]; - mp_bluetooth_get_device_addr(addr); - return mp_obj_new_bytes(addr, MP_ARRAY_SIZE(addr)); +STATIC mp_obj_t bluetooth_ble_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + mp_obj_bluetooth_ble_t *self = MP_OBJ_TO_PTR(args[0]); + + if (kwargs->used == 0) { + // Get config value + if (n_args != 2) { + mp_raise_TypeError("must query one param"); + } + + switch (mp_obj_str_get_qstr(args[1])) { + case MP_QSTR_mac: { + uint8_t addr[6]; + mp_bluetooth_get_device_addr(addr); + return mp_obj_new_bytes(addr, MP_ARRAY_SIZE(addr)); + } + default: + mp_raise_ValueError("unknown config param"); + } } else { - mp_raise_ValueError("unknown config param"); + // Set config value(s) + if (n_args != 1) { + mp_raise_TypeError("can't specify pos and kw args"); + } + + for (size_t i = 0; i < kwargs->alloc; ++i) { + if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) { + mp_map_elem_t *e = &kwargs->table[i]; + switch (mp_obj_str_get_qstr(e->key)) { + case MP_QSTR_rxbuf: { + // Determine new buffer sizes + mp_int_t ringbuf_alloc = mp_obj_get_int(e->value); + if (ringbuf_alloc < 16 || ringbuf_alloc > 0xffff) { + mp_raise_ValueError(NULL); + } + size_t irq_data_alloc = MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN(ringbuf_alloc); + + // Allocate new buffers + uint8_t *ringbuf = m_new(uint8_t, ringbuf_alloc); + uint8_t *irq_data = m_new(uint8_t, irq_data_alloc); + + // Get old buffer sizes and pointers + uint8_t *old_ringbuf_buf = self->ringbuf.buf; + size_t old_ringbuf_alloc = self->ringbuf.size; + uint8_t *old_irq_data_buf = (uint8_t*)self->irq_data_data.data; + size_t old_irq_data_alloc = self->irq_data_data_alloc; + + // Atomically update the ringbuf and irq data + MICROPY_PY_BLUETOOTH_ENTER + self->ringbuf.size = ringbuf_alloc; + self->ringbuf.buf = ringbuf; + self->ringbuf.iget = 0; + self->ringbuf.iput = 0; + self->irq_data_data_alloc = irq_data_alloc; + self->irq_data_data.data = irq_data; + MICROPY_PY_BLUETOOTH_EXIT + + // Free old buffers + m_del(uint8_t, old_ringbuf_buf, old_ringbuf_alloc); + m_del(uint8_t, old_irq_data_buf, old_irq_data_alloc); + break; + } + default: + mp_raise_ValueError("unknown config param"); + } + } + } + + return mp_const_none; } } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_config_obj, bluetooth_ble_config); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_config_obj, 1, bluetooth_ble_config); STATIC mp_obj_t bluetooth_ble_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_handler, ARG_trigger }; @@ -741,8 +807,8 @@ STATIC void ringbuf_extract(ringbuf_t* ringbuf, mp_obj_tuple_t *data_tuple, size data_tuple->items[j++] = MP_OBJ_FROM_PTR(uuid); } // The code that enqueues into the ringbuf should ensure that it doesn't - // put more than MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN bytes into - // the ringbuf. + // put more than bt->irq_data_data_alloc bytes into the ringbuf, because + // that's what's available here in bt->irq_data_bytes. if (bytes_data) { bytes_data->len = ringbuf_get(ringbuf); for (int i = 0; i < bytes_data->len; ++i) { @@ -903,7 +969,7 @@ void mp_bluetooth_gap_on_scan_complete(void) { void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, bool connectable, const int8_t rssi, const uint8_t *data, size_t data_len) { MICROPY_PY_BLUETOOTH_ENTER mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); + data_len = MIN(o->irq_data_data_alloc, data_len); if (enqueue_irq(o, 1 + 6 + 1 + 1 + 1 + data_len, MP_BLUETOOTH_IRQ_SCAN_RESULT)) { ringbuf_put(&o->ringbuf, addr_type); for (int i = 0; i < 6; ++i) { @@ -962,7 +1028,7 @@ void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t hand size_t mp_bluetooth_gattc_on_data_available_start(uint16_t event, uint16_t conn_handle, uint16_t value_handle, size_t data_len) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); - data_len = MIN(MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_BYTES_LEN, data_len); + data_len = MIN(o->irq_data_data_alloc, data_len); if (enqueue_irq(o, 2 + 2 + 1 + data_len, event)) { ringbuf_put16(&o->ringbuf, conn_handle); ringbuf_put16(&o->ringbuf, value_handle); From 9ca8a503ed3d7b31fc1cfe0e2e51925d3c0c3396 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 4 Dec 2019 22:44:49 +1100 Subject: [PATCH 0748/1299] esp32/boards: Enable ULP in base sdk configuration. Fixes issue #5159. --- ports/esp32/boards/sdkconfig.base | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index 2c77c209079ef..dcb7742d3d474 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -32,6 +32,9 @@ CONFIG_LWIP_PPP_CHAP_SUPPORT=y # Use 4kiB output buffer instead of default 16kiB (because IDF heap is fragmented in 4.0) CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +# ULP coprocessor support +CONFIG_ESP32_ULP_COPROC_ENABLED=y + # v3.3-only (renamed in 4.0) CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=n @@ -41,3 +44,4 @@ CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y CONFIG_PPP_SUPPORT=y CONFIG_PPP_PAP_SUPPORT=y CONFIG_PPP_CHAP_SUPPORT=y +CONFIG_ULP_COPROC_ENABLED=y From d61e7a6d8a146f0dd528ebc398c576d69a78f41c Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Thu, 5 Dec 2019 00:46:24 +1100 Subject: [PATCH 0749/1299] stm32/uart: Add support for UART4/5 on L0 MCUs. --- ports/stm32/mpconfigboard_common.h | 2 +- ports/stm32/stm32_it.c | 9 +++++++++ ports/stm32/uart.c | 8 ++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index e0c77719e374d..ce5c715ac576c 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -196,7 +196,7 @@ #define PYB_EXTI_NUM_VECTORS (30) // TODO (22 configurable, 7 direct) #define MICROPY_HW_MAX_I2C (3) #define MICROPY_HW_MAX_TIMER (22) -#define MICROPY_HW_MAX_UART (4) +#define MICROPY_HW_MAX_UART (5) // Configuration for STM32L4 series #elif defined(STM32L4) diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 3a4709d9fc6b5..e12cf4bf29920 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -731,6 +731,15 @@ void USART3_8_IRQHandler(void) { IRQ_EXIT(USART3_8_IRQn); } +#elif defined(STM32L0) + +void USART4_5_IRQHandler(void) { + IRQ_ENTER(USART4_5_IRQn); + uart_irq_handler(4); + uart_irq_handler(5); + IRQ_EXIT(USART4_5_IRQn); +} + #else void USART3_IRQHandler(void) { diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 72bb53f800603..d2d234a2c8e6e 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -247,6 +247,10 @@ bool uart_init(pyb_uart_obj_t *uart_obj, UARTx = USART4; irqn = USART3_8_IRQn; __HAL_RCC_USART4_CLK_ENABLE(); + #elif defined(STM32L0) + UARTx = USART4; + irqn = USART4_5_IRQn; + __HAL_RCC_USART4_CLK_ENABLE(); #else UARTx = UART4; irqn = UART4_IRQn; @@ -274,6 +278,10 @@ bool uart_init(pyb_uart_obj_t *uart_obj, UARTx = USART5; irqn = USART3_8_IRQn; __HAL_RCC_USART5_CLK_ENABLE(); + #elif defined(STM32L0) + UARTx = USART5; + irqn = USART4_5_IRQn; + __HAL_RCC_USART5_CLK_ENABLE(); #else UARTx = UART5; irqn = UART5_IRQn; From 210d05328664ebd2f106d9a3569c5e5e1b4b79ed Mon Sep 17 00:00:00 2001 From: Andrej Krejcir Date: Tue, 3 Dec 2019 23:01:26 +0100 Subject: [PATCH 0750/1299] nrf/main: Execute boot.py/main.py frozen modules without a file system. When the file system is not enabled, the boot.py and main.py modules will still be executed, if they are frozen. --- ports/nrf/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/nrf/main.c b/ports/nrf/main.c index f7d42060e830e..9ffe7a285c9e0 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -230,7 +230,7 @@ pin_init0(); led_state(1, 0); -#if MICROPY_VFS || MICROPY_MBFS +#if MICROPY_VFS || MICROPY_MBFS || MICROPY_MODULE_FROZEN // run boot.py and main.py if they exist. pyexec_file_if_exists("boot.py"); pyexec_file_if_exists("main.py"); From cc634b9e92cffa4ddbc6ccf60e346f550e7b0364 Mon Sep 17 00:00:00 2001 From: Damiano Mazzella Date: Thu, 5 Dec 2019 00:16:10 +0100 Subject: [PATCH 0751/1299] stm32/boards/xxx_WB55: Enable littlefs2 on WB55 boards. --- ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h | 1 + ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk | 1 + ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h | 1 + ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk | 1 + 4 files changed, 4 insertions(+) diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h index 54747cb04de13..2992ccce71772 100644 --- a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.h @@ -7,6 +7,7 @@ #define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_ADC (0) diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk index cd9f104ef5328..416364df9ef6d 100644 --- a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk @@ -7,3 +7,4 @@ STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb # MicroPython settings MICROPY_PY_BLUETOOTH = 1 MICROPY_BLUETOOTH_NIMBLE = 1 +MICROPY_VFS_LFS2 = 1 diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h index eeedfb0844143..0ff751d613a54 100644 --- a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.h @@ -7,6 +7,7 @@ #define MICROPY_PY_PYB_LEGACY (0) +#define MICROPY_HW_HAS_FLASH (1) #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_ADC (0) diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk index cd9f104ef5328..416364df9ef6d 100644 --- a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk +++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk @@ -7,3 +7,4 @@ STARTUP_FILE = lib/stm32lib/CMSIS/STM32WBxx/Source/Templates/gcc/startup_stm32wb # MicroPython settings MICROPY_PY_BLUETOOTH = 1 MICROPY_BLUETOOTH_NIMBLE = 1 +MICROPY_VFS_LFS2 = 1 From 2df6a0436deaf2cd1587c35140c8f48ec2e3fa6a Mon Sep 17 00:00:00 2001 From: Daniel Mizyrycki Date: Thu, 5 Dec 2019 17:07:51 -0800 Subject: [PATCH 0752/1299] nrf/boards/particle_xenon: Enable USB CDC on Particle Xenon board. --- ports/nrf/boards/particle_xenon/mpconfigboard.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h index c2aabce48d7aa..4d8e8337a5487 100644 --- a/ports/nrf/boards/particle_xenon/mpconfigboard.h +++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h @@ -38,6 +38,8 @@ #define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_RANDOM_HW_RNG (1) +#define MICROPY_HW_USB_CDC (1) + #define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_LED_TRICOLOR (1) #define MICROPY_HW_LED_PULLUP (1) From 50dc5f10a64198d2e3cd16e3b6cc831a241ec6b2 Mon Sep 17 00:00:00 2001 From: Daniel Mizyrycki Date: Fri, 6 Dec 2019 08:28:36 -0800 Subject: [PATCH 0753/1299] docs/reference/filesystem: Fix typo in block device code example. --- docs/reference/filesystem.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/filesystem.rst b/docs/reference/filesystem.rst index 71d34e795407a..99e23053136af 100644 --- a/docs/reference/filesystem.rst +++ b/docs/reference/filesystem.rst @@ -124,7 +124,7 @@ interface (i.e. both signatures and behaviours of the self.block_size = block_size self.data = bytearray(block_size * num_blocks) - def readblocks(self, block, buf, offset=0): + def readblocks(self, block_num, buf, offset=0): addr = block_num * self.block_size + offset for i in range(len(buf)): buf[i] = self.data[addr + i] From 381be9a745a2895f6333e5d7443f6d32fbe524de Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 9 Dec 2019 14:21:22 +1100 Subject: [PATCH 0754/1299] docs/reference/filesystem: Add note and example about using filesystem. --- docs/reference/filesystem.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/reference/filesystem.rst b/docs/reference/filesystem.rst index 99e23053136af..32d0138491282 100644 --- a/docs/reference/filesystem.rst +++ b/docs/reference/filesystem.rst @@ -156,6 +156,13 @@ As it supports the extended interface, it can be used with :class:`littlefs os.VfsLfs2.mkfs(bdev) os.mount(bdev, '/ramdisk') +Once mounted, the filesystem (regardless of its type) can be used as it +normally would be used from Python code, for example:: + + with open('/ramdisk/hello.txt', 'w') as f: + f.write('Hello world') + print(open('/ramdisk/hello.txt').read()) + Filesystems ----------- From 193bc3702f35bc7b60ffd79e4f41ecd5db1fd383 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Sat, 7 Dec 2019 22:31:04 +1100 Subject: [PATCH 0755/1299] mpy-cross/README.md: Add notes about -march and -O. --- mpy-cross/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mpy-cross/README.md b/mpy-cross/README.md index e35b28b6969ec..bf743a903163d 100644 --- a/mpy-cross/README.md +++ b/mpy-cross/README.md @@ -22,4 +22,10 @@ the unix port of MicroPython requires the following: $ ./mpy-cross -mcache-lookup-bc foo.py +If the Python code contains `@native` or `@viper` annotations, then you must +specify `-march` to match the target architecture. + Run `./mpy-cross -h` to get a full list of options. + +The optimisation level is 0 by default. Optimisation levels are detailed in +https://docs.micropython.org/en/latest/library/micropython.html#micropython.opt_level From 4ebbacd65eec4c0fde8ceb32274c06f5e3de3af6 Mon Sep 17 00:00:00 2001 From: Emil Renner Berthing Date: Sun, 8 Dec 2019 21:43:47 +0100 Subject: [PATCH 0756/1299] py/objenumerate: Check for valid args in enumerate constructor. For the case where MICROPY_CPYTHON_COMPAT is disabled. This fix makes basics/fun_error2.py pass and not crash the interpreter. --- py/objenumerate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/objenumerate.c b/py/objenumerate.c index 493e45c2a2028..243c9f83aa8f8 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -59,7 +59,7 @@ STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, siz o->iter = mp_getiter(arg_vals.iterable.u_obj, NULL); o->cur = arg_vals.start.u_int; #else - (void)n_kw; + mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t); o->base.type = type; o->iter = mp_getiter(args[0], NULL); From b76f0a73bc31d1c8871ff00d2f93b5805b3b6315 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 9 Dec 2019 15:12:51 +1100 Subject: [PATCH 0757/1299] stm32/main: Fix SKIPSD file detection so SD card is mounted by default. The condition for skipping was accidentally inverted in 7723dac3371ccf081c2490b33b69492dc42818bd Fixes issue #5400. --- ports/stm32/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index 8cb6ed1e3bd53..fd9cdd6f67005 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -644,7 +644,7 @@ void stm32_main(uint32_t reset_mode) { // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { // if there is a file in the flash called "SKIPSD", then we don't mount the SD card - if (!mounted_flash || mp_vfs_import_stat("SKIPSD") == MP_IMPORT_STAT_FILE) { + if (!mounted_flash || mp_vfs_import_stat("SKIPSD") == MP_IMPORT_STAT_NO_EXIST) { mounted_sdcard = init_sdcard_fs(); } } From 159388f85072af9aa704f48f6d75bea5b943178b Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Dec 2019 16:58:27 +1100 Subject: [PATCH 0758/1299] docs/library/ubluetooth: Add note about API being under development. --- docs/library/ubluetooth.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index ddcd28d9e6719..1a62d1e4bac48 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -12,6 +12,9 @@ roles concurrently. This API is intended to match the low-level Bluetooth protocol and provide building-blocks for higher-level abstractions such as specific device types. +.. note:: This module is still under development and its classes, functions, + methods and constants are subject to change. + class BLE --------- From b310930dba3a35dbe4d790f461caf27d78b4c7b9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Dec 2019 16:58:53 +1100 Subject: [PATCH 0759/1299] docs/library/uos: Add notes and links about littlefs failures. --- docs/library/uos.rst | 8 ++++++++ docs/reference/filesystem.rst | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/library/uos.rst b/docs/library/uos.rst index 84d341ac210ac..5505e6434ff28 100644 --- a/docs/library/uos.rst +++ b/docs/library/uos.rst @@ -191,6 +191,9 @@ represented by VFS classes. Build a Lfs1 filesystem on *block_dev*. + .. note:: There are reports of littlefs v1 failing in certain situations, + for details see `littlefs issue 347`_. + .. class:: VfsLfs2(block_dev) Create a filesystem object that uses the `littlefs v2 filesystem format`_. @@ -204,8 +207,13 @@ represented by VFS classes. Build a Lfs2 filesystem on *block_dev*. + .. note:: There are reports of littlefs v2 failing in certain situations, + for details see `littlefs issue 295`_. + .. _littlefs v1 filesystem format: https://github.com/ARMmbed/littlefs/tree/v1 .. _littlefs v2 filesystem format: https://github.com/ARMmbed/littlefs +.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295 +.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347 Block devices ------------- diff --git a/docs/reference/filesystem.rst b/docs/reference/filesystem.rst index 32d0138491282..cd86009287ae9 100644 --- a/docs/reference/filesystem.rst +++ b/docs/reference/filesystem.rst @@ -214,13 +214,18 @@ Littlefs Littlefs_ is a filesystem designed for flash-based devices, and is much more resistant to filesystem corruption. +.. note:: There are reports of littlefs v1 and v2 failing in certain + situations, for details see `littlefs issue 347`_ and + `littlefs issue 295`_. + Note: It can be still be accessed over USB MSC using the `littlefs FUSE driver`_. Note that you must use the ``-b=4096`` option to override the block size. .. _littlefs FUSE driver: https://github.com/ARMmbed/littlefs-fuse/tree/master/littlefs - .. _Littlefs: https://github.com/ARMmbed/littlefs +.. _littlefs issue 295: https://github.com/ARMmbed/littlefs/issues/295 +.. _littlefs issue 347: https://github.com/ARMmbed/littlefs/issues/347 To format the entire flash using littlefs v2:: From b47e155bd07e5765b804c404411825b15378c0b6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 6 Oct 2019 23:29:40 +1100 Subject: [PATCH 0760/1299] py/persistentcode: Add ability to relocate loaded native code. Implements text, rodata and bss generalised relocations, as well as generic qstr-object linking. This allows importing dynamic native modules on all supported architectures in a unified way. --- ports/esp32/main.c | 6 ++- ports/esp32/mpconfigport.h | 4 +- ports/esp8266/modesp.c | 12 +++++- ports/esp8266/mpconfigport.h | 4 +- py/asmbase.h | 2 +- py/bc.h | 2 +- py/persistentcode.c | 80 +++++++++++++++++++++++++++++++++++- py/persistentcode.h | 2 + py/runtime0.h | 6 ++- 9 files changed, 106 insertions(+), 12 deletions(-) diff --git a/ports/esp32/main.c b/ports/esp32/main.c index b0d1b1537065d..d8705ee735693 100644 --- a/ports/esp32/main.c +++ b/ports/esp32/main.c @@ -47,6 +47,7 @@ #include "py/nlr.h" #include "py/compile.h" #include "py/runtime.h" +#include "py/persistentcode.h" #include "py/repl.h" #include "py/gc.h" #include "py/mphal.h" @@ -173,12 +174,15 @@ void mbedtls_debug_set_threshold(int threshold) { (void)threshold; } -void *esp_native_code_commit(void *buf, size_t len) { +void *esp_native_code_commit(void *buf, size_t len, void *reloc) { len = (len + 3) & ~3; uint32_t *p = heap_caps_malloc(len, MALLOC_CAP_EXEC); if (p == NULL) { m_malloc_fail(len); } + if (reloc) { + mp_native_relocate(reloc, buf, (uintptr_t)p); + } memcpy(p, buf, len); return p; } diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index da62beb4c1705..1924cf21860a5 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -21,8 +21,6 @@ // emitters #define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_XTENSAWIN (1) -void *esp_native_code_commit(void*, size_t); -#define MP_PLAT_COMMIT_EXEC(buf, len) esp_native_code_commit(buf, len) // compiler configuration #define MICROPY_COMP_MODULE_CONST (1) @@ -225,6 +223,8 @@ struct mp_bluetooth_nimble_root_pointers_t; #define BYTES_PER_WORD (4) #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p))) #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) +void *esp_native_code_commit(void*, size_t, void*); +#define MP_PLAT_COMMIT_EXEC(buf, len, reloc) esp_native_code_commit(buf, len, reloc) #define MP_SSIZE_MAX (0x7fffffff) // Note: these "critical nested" macros do not ensure cross-CPU exclusion, diff --git a/ports/esp8266/modesp.c b/ports/esp8266/modesp.c index 2aeb3d690a0b5..a3cc2eca7347e 100644 --- a/ports/esp8266/modesp.c +++ b/ports/esp8266/modesp.c @@ -28,6 +28,7 @@ #include "py/gc.h" #include "py/runtime.h" +#include "py/persistentcode.h" #include "py/mperrno.h" #include "py/mphal.h" #include "drivers/dht/dht.h" @@ -282,7 +283,7 @@ void esp_native_code_init(void) { esp_native_code_erased = 0; } -void *esp_native_code_commit(void *buf, size_t len) { +void *esp_native_code_commit(void *buf, size_t len, void *reloc) { //printf("COMMIT(buf=%p, len=%u, start=%08x, cur=%08x, end=%08x, erased=%08x)\n", buf, len, esp_native_code_start, esp_native_code_cur, esp_native_code_end, esp_native_code_erased); len = (len + 3) & ~3; @@ -294,6 +295,14 @@ void *esp_native_code_commit(void *buf, size_t len) { void *dest; if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) { dest = (void*)esp_native_code_cur; + } else { + dest = (void*)(FLASH_START + esp_native_code_cur); + } + if (reloc) { + mp_native_relocate(reloc, buf, (uintptr_t)dest); + } + + if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) { memcpy(dest, buf, len); } else { SpiFlashOpResult res; @@ -313,7 +322,6 @@ void *esp_native_code_commit(void *buf, size_t len) { if (res != SPI_FLASH_RESULT_OK) { mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO); } - dest = (void*)(FLASH_START + esp_native_code_cur); } esp_native_code_cur += len; diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 22ca99b2b18b7..81544bb2a3fb4 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -131,8 +131,8 @@ typedef uint32_t sys_prot_t; // for modlwip #include #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) -void *esp_native_code_commit(void*, size_t); -#define MP_PLAT_COMMIT_EXEC(buf, len) esp_native_code_commit(buf, len) +void *esp_native_code_commit(void*, size_t, void*); +#define MP_PLAT_COMMIT_EXEC(buf, len, reloc) esp_native_code_commit(buf, len, reloc) // printer for debugging output, goes to UART only extern const struct _mp_print_t mp_debug_print; diff --git a/py/asmbase.h b/py/asmbase.h index d2b40389310ed..b5e259358d4e5 100644 --- a/py/asmbase.h +++ b/py/asmbase.h @@ -60,7 +60,7 @@ static inline size_t mp_asm_base_get_code_size(mp_asm_base_t *as) { static inline void *mp_asm_base_get_code(mp_asm_base_t *as) { #if defined(MP_PLAT_COMMIT_EXEC) - return MP_PLAT_COMMIT_EXEC(as->code_base, as->code_size); + return MP_PLAT_COMMIT_EXEC(as->code_base, as->code_size, NULL); #else return as->code_base; #endif diff --git a/py/bc.h b/py/bc.h index fd52571fdabef..a96d17a0db682 100644 --- a/py/bc.h +++ b/py/bc.h @@ -74,7 +74,7 @@ #define MP_BC_PRELUDE_SIG_ENCODE(S, E, scope, out_byte, out_env) \ do { \ /*// Get values to store in prelude */ \ - size_t F = scope->scope_flags & 0x0f; /* only need to store lower 4 flag bits */ \ + size_t F = scope->scope_flags & MP_SCOPE_FLAG_ALL_SIG; \ size_t A = scope->num_pos_args; \ size_t K = scope->num_kwonly_args; \ size_t D = scope->num_def_pos_args; \ diff --git a/py/persistentcode.c b/py/persistentcode.c index 84385c1713fef..353fa268e5c08 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -33,6 +33,7 @@ #include "py/emitglue.h" #include "py/persistentcode.h" #include "py/bc0.h" +#include "py/objstr.h" #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE @@ -145,8 +146,16 @@ STATIC byte *extract_prelude(const byte **ip, bytecode_prelude_t *prelude) { #include "py/parsenum.h" +STATIC int read_byte(mp_reader_t *reader); +STATIC size_t read_uint(mp_reader_t *reader, byte **out); + #if MICROPY_EMIT_MACHINE_CODE +typedef struct _reloc_info_t { + mp_reader_t *reader; + mp_uint_t *const_table; +} reloc_info_t; + #if MICROPY_EMIT_THUMB STATIC void asm_thumb_rewrite_mov(uint8_t *pc, uint16_t val) { // high part @@ -179,6 +188,52 @@ STATIC void arch_link_qstr(uint8_t *pc, bool is_obj, qstr qst) { #endif } +void mp_native_relocate(void *ri_in, uint8_t *text, uintptr_t reloc_text) { + // Relocate native code + reloc_info_t *ri = ri_in; + uint8_t op; + uintptr_t *addr_to_adjust = NULL; + while ((op = read_byte(ri->reader)) != 0xff) { + if (op & 1) { + // Point to new location to make adjustments + size_t addr = read_uint(ri->reader, NULL); + if ((addr & 1) == 0) { + // Point to somewhere in text + addr_to_adjust = &((uintptr_t*)text)[addr >> 1]; + } else { + // Point to somewhere in rodata + addr_to_adjust = &((uintptr_t*)ri->const_table[1])[addr >> 1]; + } + } + op >>= 1; + uintptr_t dest; + size_t n = 1; + if (op <= 5) { + if (op & 1) { + // Read in number of adjustments to make + n = read_uint(ri->reader, NULL); + } + op >>= 1; + if (op == 0) { + // Destination is text + dest = reloc_text; + } else { + // Destination is rodata (op=1) or bss (op=1 if no rodata, else op=2) + dest = ri->const_table[op]; + } + } else if (op == 6) { + // Destination is mp_fun_table itself + dest = (uintptr_t)&mp_fun_table; + } else { + // Destination is an entry in mp_fun_table + dest = ((uintptr_t*)&mp_fun_table)[op - 7]; + } + while (n--) { + *addr_to_adjust++ += dest; + } + } +} + #endif STATIC int read_byte(mp_reader_t *reader) { @@ -340,6 +395,9 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { // Generic 16-bit link dest[0] = qst & 0xff; dest[1] = (qst >> 8) & 0xff; + } else if ((off & 3) == 3) { + // Generic, aligned qstr-object link + *(mp_obj_t*)dest = MP_OBJ_NEW_QSTR(qst); } else { // Architecture-specific link arch_link_qstr(dest, (off & 3) == 2, qst); @@ -423,8 +481,26 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { #if MICROPY_EMIT_MACHINE_CODE } else { + mp_uint_t *ct = &const_table[1]; + if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) { + size_t size = read_uint(reader, NULL); + uint8_t *rodata = m_new(uint8_t, size); + read_bytes(reader, rodata, size); + *ct++ = (uintptr_t)rodata; + } + if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) { + size_t size = read_uint(reader, NULL); + uint8_t *bss = m_new0(uint8_t, size); + *ct++ = (uintptr_t)bss; + } + reloc_info_t ri = {reader, const_table}; #if defined(MP_PLAT_COMMIT_EXEC) - fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len); + void *opt_ri = (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) ? &ri : NULL; + fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len, opt_ri); + #else + if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) { + mp_native_relocate(&ri, fun_data, (uintptr_t)fun_data); + } #endif mp_emit_glue_assign_native(rc, kind, @@ -624,7 +700,7 @@ STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc, qstr_window_t *q save_prelude_qstrs(print, qstr_window, ip_info); } else { // Save basic scope info for viper and asm - mp_print_uint(print, rc->scope_flags); + mp_print_uint(print, rc->scope_flags & MP_SCOPE_FLAG_ALL_SIG); prelude.n_pos_args = 0; prelude.n_kwonly_args = 0; if (rc->kind == MP_CODE_NATIVE_ASM) { diff --git a/py/persistentcode.h b/py/persistentcode.h index 07e018f8a6248..fde7a4625dceb 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -95,4 +95,6 @@ mp_raw_code_t *mp_raw_code_load_file(const char *filename); void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print); void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename); +void mp_native_relocate(void *reloc, uint8_t *text, uintptr_t reloc_text); + #endif // MICROPY_INCLUDED_PY_PERSISTENTCODE_H diff --git a/py/runtime0.h b/py/runtime0.h index f588110c0d7a4..b433c716f7b1f 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -28,13 +28,17 @@ // The first four must fit in 8 bits, see emitbc.c // The remaining must fit in 16 bits, see scope.h +#define MP_SCOPE_FLAG_ALL_SIG (0x0f) #define MP_SCOPE_FLAG_GENERATOR (0x01) #define MP_SCOPE_FLAG_VARKEYWORDS (0x02) #define MP_SCOPE_FLAG_VARARGS (0x04) #define MP_SCOPE_FLAG_DEFKWARGS (0x08) #define MP_SCOPE_FLAG_REFGLOBALS (0x10) // used only if native emitter enabled #define MP_SCOPE_FLAG_HASCONSTS (0x20) // used only if native emitter enabled -#define MP_SCOPE_FLAG_VIPERRET_POS (6) // 3 bits used for viper return type +#define MP_SCOPE_FLAG_VIPERRET_POS (6) // 3 bits used for viper return type, to pass from compiler to native emitter +#define MP_SCOPE_FLAG_VIPERRELOC (0x10) // used only when loading viper from .mpy +#define MP_SCOPE_FLAG_VIPERRODATA (0x20) // used only when loading viper from .mpy +#define MP_SCOPE_FLAG_VIPERBSS (0x40) // used only when loading viper from .mpy // types for native (viper) function signature #define MP_NATIVE_TYPE_OBJ (0x00) From 360d972c16dd818462be7699badb6478639924c1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 7 Oct 2019 11:56:24 +1100 Subject: [PATCH 0761/1299] py/nativeglue: Add new header file with native function table typedef. --- py/emitnative.c | 4 +- py/emitnx86.c | 2 +- py/nativeglue.c | 5 +- py/nativeglue.h | 141 ++++++++++++++++++++++++++++++++++++++++++++ py/persistentcode.c | 4 +- py/runtime0.h | 56 ------------------ tools/mpy-tool.py | 3 +- 7 files changed, 150 insertions(+), 65 deletions(-) create mode 100644 py/nativeglue.h diff --git a/py/emitnative.c b/py/emitnative.c index fbf6659140383..07b984b780f70 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -47,7 +47,7 @@ #include #include "py/emit.h" -#include "py/bc.h" +#include "py/nativeglue.h" #include "py/objstr.h" #if MICROPY_DEBUG_VERBOSE // print debugging info @@ -687,7 +687,7 @@ STATIC void emit_native_end_pass(emit_t *emit) { #if !MICROPY_DYNAMIC_COMPILER // Store mp_fun_table pointer just after qstrs // (but in dynamic-compiler mode eliminate dependency on mp_fun_table) - emit->const_table[nqstr] = (mp_uint_t)(uintptr_t)mp_fun_table; + emit->const_table[nqstr] = (mp_uint_t)(uintptr_t)&mp_fun_table; #endif #if MICROPY_PERSISTENT_CODE_SAVE diff --git a/py/emitnx86.c b/py/emitnx86.c index 790cae04c29e4..f0553f0682bb9 100644 --- a/py/emitnx86.c +++ b/py/emitnx86.c @@ -1,7 +1,7 @@ // x86 specific stuff #include "py/mpconfig.h" -#include "py/runtime0.h" +#include "py/nativeglue.h" #if MICROPY_EMIT_X86 diff --git a/py/nativeglue.c b/py/nativeglue.c index 08fbd3c309f3b..9991151a34f7a 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -30,8 +30,7 @@ #include "py/runtime.h" #include "py/smallint.h" -#include "py/emitglue.h" -#include "py/bc.h" +#include "py/nativeglue.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_printf DEBUG_printf @@ -211,7 +210,7 @@ STATIC bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *re } // these must correspond to the respective enum in runtime0.h -const void *const mp_fun_table[MP_F_NUMBER_OF] = { +const mp_fun_table_t mp_fun_table = { &mp_const_none_obj, &mp_const_false_obj, &mp_const_true_obj, diff --git a/py/nativeglue.h b/py/nativeglue.h new file mode 100644 index 0000000000000..200093b3cc968 --- /dev/null +++ b/py/nativeglue.h @@ -0,0 +1,141 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_PY_NATIVEGLUE_H +#define MICROPY_INCLUDED_PY_NATIVEGLUE_H + +#include "py/obj.h" +#include "py/persistentcode.h" + +typedef enum { + MP_F_CONST_NONE_OBJ = 0, + MP_F_CONST_FALSE_OBJ, + MP_F_CONST_TRUE_OBJ, + MP_F_CONVERT_OBJ_TO_NATIVE, + MP_F_CONVERT_NATIVE_TO_OBJ, + MP_F_NATIVE_SWAP_GLOBALS, + MP_F_LOAD_NAME, + MP_F_LOAD_GLOBAL, + MP_F_LOAD_BUILD_CLASS, + MP_F_LOAD_ATTR, + MP_F_LOAD_METHOD, + MP_F_LOAD_SUPER_METHOD, + MP_F_STORE_NAME, + MP_F_STORE_GLOBAL, + MP_F_STORE_ATTR, + MP_F_OBJ_SUBSCR, + MP_F_OBJ_IS_TRUE, + MP_F_UNARY_OP, + MP_F_BINARY_OP, + MP_F_BUILD_TUPLE, + MP_F_BUILD_LIST, + MP_F_BUILD_MAP, + MP_F_BUILD_SET, + MP_F_STORE_SET, + MP_F_LIST_APPEND, + MP_F_STORE_MAP, + MP_F_MAKE_FUNCTION_FROM_RAW_CODE, + MP_F_NATIVE_CALL_FUNCTION_N_KW, + MP_F_CALL_METHOD_N_KW, + MP_F_CALL_METHOD_N_KW_VAR, + MP_F_NATIVE_GETITER, + MP_F_NATIVE_ITERNEXT, + MP_F_NLR_PUSH, + MP_F_NLR_POP, + MP_F_NATIVE_RAISE, + MP_F_IMPORT_NAME, + MP_F_IMPORT_FROM, + MP_F_IMPORT_ALL, + MP_F_NEW_SLICE, + MP_F_UNPACK_SEQUENCE, + MP_F_UNPACK_EX, + MP_F_DELETE_NAME, + MP_F_DELETE_GLOBAL, + MP_F_MAKE_CLOSURE_FROM_RAW_CODE, + MP_F_ARG_CHECK_NUM_SIG, + MP_F_SETUP_CODE_STATE, + MP_F_SMALL_INT_FLOOR_DIVIDE, + MP_F_SMALL_INT_MODULO, + MP_F_NATIVE_YIELD_FROM, + MP_F_SETJMP, + MP_F_NUMBER_OF, +} mp_fun_kind_t; + +typedef struct _mp_fun_table_t { + mp_const_obj_t const_none; + mp_const_obj_t const_false; + mp_const_obj_t const_true; + mp_uint_t (*native_from_obj)(mp_obj_t obj, mp_uint_t type); + mp_obj_t (*native_to_obj)(mp_uint_t val, mp_uint_t type); + mp_obj_dict_t *(*swap_globals)(mp_obj_dict_t *new_globals); + mp_obj_t (*load_name)(qstr qst); + mp_obj_t (*load_global)(qstr qst); + mp_obj_t (*load_build_class)(void); + mp_obj_t (*load_attr)(mp_obj_t base, qstr attr); + void (*load_method)(mp_obj_t base, qstr attr, mp_obj_t *dest); + void (*load_super_method)(qstr attr, mp_obj_t *dest); + void (*store_name)(qstr qst, mp_obj_t obj); + void (*store_global)(qstr qst, mp_obj_t obj); + void (*store_attr)(mp_obj_t base, qstr attr, mp_obj_t val); + mp_obj_t (*obj_subscr)(mp_obj_t base, mp_obj_t index, mp_obj_t val); + bool (*obj_is_true)(mp_obj_t arg); + mp_obj_t (*unary_op)(mp_unary_op_t op, mp_obj_t arg); + mp_obj_t (*binary_op)(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs); + mp_obj_t (*new_tuple)(size_t n, const mp_obj_t *items); + mp_obj_t (*new_list)(size_t n, mp_obj_t *items); + mp_obj_t (*new_dict)(size_t n_args); + mp_obj_t (*new_set)(size_t n_args, mp_obj_t *items); + void (*set_store)(mp_obj_t self_in, mp_obj_t item); + mp_obj_t (*list_append)(mp_obj_t self_in, mp_obj_t arg); + mp_obj_t (*dict_store)(mp_obj_t self_in, mp_obj_t key, mp_obj_t value); + mp_obj_t (*make_function_from_raw_code)(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args); + mp_obj_t (*call_function_n_kw)(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args); + mp_obj_t (*call_method_n_kw)(size_t n_args, size_t n_kw, const mp_obj_t *args); + mp_obj_t (*call_method_n_kw_var)(bool have_self, size_t n_args_n_kw, const mp_obj_t *args); + mp_obj_t (*getiter)(mp_obj_t obj, mp_obj_iter_buf_t *iter); + mp_obj_t (*iternext)(mp_obj_iter_buf_t *iter); + unsigned int (*nlr_push)(nlr_buf_t *); + void (*nlr_pop)(void); + void (*raise)(mp_obj_t o); + mp_obj_t (*import_name)(qstr name, mp_obj_t fromlist, mp_obj_t level); + mp_obj_t (*import_from)(mp_obj_t module, qstr name); + void (*import_all)(mp_obj_t module); + mp_obj_t (*new_slice)(mp_obj_t start, mp_obj_t stop, mp_obj_t step); + void (*unpack_sequence)(mp_obj_t seq, size_t num, mp_obj_t *items); + void (*unpack_ex)(mp_obj_t seq, size_t num, mp_obj_t *items); + void (*delete_name)(qstr qst); + void (*delete_global)(qstr qst); + mp_obj_t (*make_closure_from_raw_code)(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args); + void (*arg_check_num_sig)(size_t n_args, size_t n_kw, uint32_t sig); + void (*setup_code_state)(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args); + mp_int_t (*small_int_floor_divide)(mp_int_t num, mp_int_t denom); + mp_int_t (*small_int_modulo)(mp_int_t dividend, mp_int_t divisor); + bool (*yield_from)(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value); + void *setjmp; +} mp_fun_table_t; + +extern const mp_fun_table_t mp_fun_table; + +#endif // MICROPY_INCLUDED_PY_NATIVEGLUE_H diff --git a/py/persistentcode.c b/py/persistentcode.c index 353fa268e5c08..1e3b5368b43ae 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -30,7 +30,7 @@ #include #include "py/reader.h" -#include "py/emitglue.h" +#include "py/nativeglue.h" #include "py/persistentcode.h" #include "py/bc0.h" #include "py/objstr.h" @@ -453,7 +453,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { #if MICROPY_EMIT_MACHINE_CODE if (kind != MP_CODE_BYTECODE) { // Populate mp_fun_table entry - *ct++ = (mp_uint_t)(uintptr_t)mp_fun_table; + *ct++ = (mp_uint_t)(uintptr_t)&mp_fun_table; } #endif diff --git a/py/runtime0.h b/py/runtime0.h index b433c716f7b1f..e6eeff97d6868 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -156,60 +156,4 @@ typedef enum { MP_BINARY_OP_IS_NOT, } mp_binary_op_t; -typedef enum { - MP_F_CONST_NONE_OBJ = 0, - MP_F_CONST_FALSE_OBJ, - MP_F_CONST_TRUE_OBJ, - MP_F_CONVERT_OBJ_TO_NATIVE, - MP_F_CONVERT_NATIVE_TO_OBJ, - MP_F_NATIVE_SWAP_GLOBALS, - MP_F_LOAD_NAME, - MP_F_LOAD_GLOBAL, - MP_F_LOAD_BUILD_CLASS, - MP_F_LOAD_ATTR, - MP_F_LOAD_METHOD, - MP_F_LOAD_SUPER_METHOD, - MP_F_STORE_NAME, - MP_F_STORE_GLOBAL, - MP_F_STORE_ATTR, - MP_F_OBJ_SUBSCR, - MP_F_OBJ_IS_TRUE, - MP_F_UNARY_OP, - MP_F_BINARY_OP, - MP_F_BUILD_TUPLE, - MP_F_BUILD_LIST, - MP_F_BUILD_MAP, - MP_F_BUILD_SET, - MP_F_STORE_SET, - MP_F_LIST_APPEND, - MP_F_STORE_MAP, - MP_F_MAKE_FUNCTION_FROM_RAW_CODE, - MP_F_NATIVE_CALL_FUNCTION_N_KW, - MP_F_CALL_METHOD_N_KW, - MP_F_CALL_METHOD_N_KW_VAR, - MP_F_NATIVE_GETITER, - MP_F_NATIVE_ITERNEXT, - MP_F_NLR_PUSH, - MP_F_NLR_POP, - MP_F_NATIVE_RAISE, - MP_F_IMPORT_NAME, - MP_F_IMPORT_FROM, - MP_F_IMPORT_ALL, - MP_F_NEW_SLICE, - MP_F_UNPACK_SEQUENCE, - MP_F_UNPACK_EX, - MP_F_DELETE_NAME, - MP_F_DELETE_GLOBAL, - MP_F_MAKE_CLOSURE_FROM_RAW_CODE, - MP_F_ARG_CHECK_NUM_SIG, - MP_F_SETUP_CODE_STATE, - MP_F_SMALL_INT_FLOOR_DIVIDE, - MP_F_SMALL_INT_MODULO, - MP_F_NATIVE_YIELD_FROM, - MP_F_SETJMP, - MP_F_NUMBER_OF, -} mp_fun_kind_t; - -extern const void *const mp_fun_table[MP_F_NUMBER_OF]; - #endif // MICROPY_INCLUDED_PY_RUNTIME0_H diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 581603249d346..cd36c909f4175 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -314,7 +314,7 @@ def freeze_constants(self): print(' MP_ROM_QSTR(%s),' % global_qstrs[qst].qstr_id) for i in range(len(self.objs)): if self.objs[i] is MPFunTable: - print(' mp_fun_table,') + print(' &mp_fun_table,') elif type(self.objs[i]) is float: print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B') print(' MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i)) @@ -711,6 +711,7 @@ def freeze_mpy(base_qstrs, raw_codes): print('#include "py/objint.h"') print('#include "py/objstr.h"') print('#include "py/emitglue.h"') + print('#include "py/nativeglue.h"') print() print('#if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE != %u' % config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) From 3690f79afc4e32acbd1db243fd7af7fa518fa27f Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 8 Oct 2019 23:00:34 +1100 Subject: [PATCH 0762/1299] py/nativeglue: Add funcs/types to native glue table for dynamic runtime. These allow discovery of symbols by native code that is loaded dynamically. --- py/nativeglue.c | 29 +++++++++++++++++++++++++++++ py/nativeglue.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/py/nativeglue.c b/py/nativeglue.c index 9991151a34f7a..a88d8c1b9ba30 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include #include #include @@ -31,6 +32,7 @@ #include "py/runtime.h" #include "py/smallint.h" #include "py/nativeglue.h" +#include "py/gc.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_printf DEBUG_printf @@ -269,6 +271,33 @@ const mp_fun_table_t mp_fun_table = { #else NULL, #endif + // Additional entries for dynamic runtime, starts at index 50 + memset, + memmove, + gc_realloc, + mp_printf, + mp_vprintf, + mp_raise_msg, + mp_obj_get_type, + mp_obj_new_str, + mp_obj_new_bytes, + mp_obj_new_bytearray_by_ref, + mp_get_buffer_raise, + mp_get_stream_raise, + &mp_plat_print, + &mp_type_type, + &mp_type_str, + &mp_type_list, + &mp_type_dict, + &mp_type_fun_builtin_0, + &mp_type_fun_builtin_1, + &mp_type_fun_builtin_2, + &mp_type_fun_builtin_3, + &mp_type_fun_builtin_var, + &mp_stream_read_obj, + &mp_stream_readinto_obj, + &mp_stream_unbuffered_readline_obj, + &mp_stream_write_obj, }; #endif // MICROPY_EMIT_NATIVE diff --git a/py/nativeglue.h b/py/nativeglue.h index 200093b3cc968..9abae89df2127 100644 --- a/py/nativeglue.h +++ b/py/nativeglue.h @@ -26,8 +26,10 @@ #ifndef MICROPY_INCLUDED_PY_NATIVEGLUE_H #define MICROPY_INCLUDED_PY_NATIVEGLUE_H +#include #include "py/obj.h" #include "py/persistentcode.h" +#include "py/stream.h" typedef enum { MP_F_CONST_NONE_OBJ = 0, @@ -134,6 +136,36 @@ typedef struct _mp_fun_table_t { mp_int_t (*small_int_modulo)(mp_int_t dividend, mp_int_t divisor); bool (*yield_from)(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value); void *setjmp; + // Additional entries for dynamic runtime, starts at index 50 + void *(*memset_)(void *s, int c, size_t n); + void *(*memmove_)(void *dest, const void *src, size_t n); + void *(*realloc_)(void *ptr, size_t n_bytes, bool allow_move); + int (*printf_)(const mp_print_t *print, const char *fmt, ...); + int (*vprintf_)(const mp_print_t *print, const char *fmt, va_list args); + #if defined(__GNUC__) + NORETURN // Only certain compilers support no-return attributes in function pointer declarations + #endif + void (*raise_msg)(const mp_obj_type_t *exc_type, const char *msg); + mp_obj_type_t *(*obj_get_type)(mp_const_obj_t o_in); + mp_obj_t (*obj_new_str)(const char* data, size_t len); + mp_obj_t (*obj_new_bytes)(const byte* data, size_t len); + mp_obj_t (*obj_new_bytearray_by_ref)(size_t n, void *items); + void (*get_buffer_raise)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); + const mp_stream_p_t *(*get_stream_raise)(mp_obj_t self_in, int flags); + const mp_print_t *plat_print; + const mp_obj_type_t *type_type; + const mp_obj_type_t *type_str; + const mp_obj_type_t *type_list; + const mp_obj_type_t *type_dict; + const mp_obj_type_t *type_fun_builtin_0; + const mp_obj_type_t *type_fun_builtin_1; + const mp_obj_type_t *type_fun_builtin_2; + const mp_obj_type_t *type_fun_builtin_3; + const mp_obj_type_t *type_fun_builtin_var; + const mp_obj_fun_builtin_var_t *stream_read_obj; + const mp_obj_fun_builtin_var_t *stream_readinto_obj; + const mp_obj_fun_builtin_var_t *stream_unbuffered_readline_obj; + const mp_obj_fun_builtin_var_t *stream_write_obj; } mp_fun_table_t; extern const mp_fun_table_t mp_fun_table; From 27879844d24f276b0d15b27bd60c3a0391a9099e Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 9 Oct 2019 14:23:15 +1100 Subject: [PATCH 0763/1299] tools/mpy-tool.py: Add ability to merge multiple .mpy files into one. Usage: mpy-tool.py -o merged.mpy --merge mod1.mpy mod2.mpy The constituent .mpy files are executed sequentially when the merged file is imported, and they all use the same global namespace. --- tools/mpy-tool.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index cd36c909f4175..8bc37734c7034 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -691,7 +691,10 @@ def read_mpy(filename): raise Exception('native architecture mismatch') config.mp_small_int_bits = header[3] qstr_win = QStrWindow(qw_size) - return read_raw_code(f, qstr_win) + rc = read_raw_code(f, qstr_win) + rc.mpy_source_file = filename + rc.qstr_win_size = qw_size + return rc def dump_mpy(raw_codes): for rc in raw_codes: @@ -789,6 +792,55 @@ def freeze_mpy(base_qstrs, raw_codes): print(' &raw_code_%s,' % rc.escaped_name) print('};') +def merge_mpy(raw_codes, output_file): + assert len(raw_codes) <= 31 # so var-uints all fit in 1 byte + merged_mpy = bytearray() + + if len(raw_codes) == 1: + with open(raw_codes[0].mpy_source_file, 'rb') as f: + merged_mpy.extend(f.read()) + else: + header = bytearray(5) + header[0] = ord('M') + header[1] = config.MPY_VERSION + header[2] = (config.native_arch << 2 + | config.MICROPY_PY_BUILTINS_STR_UNICODE << 1 + | config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) + header[3] = config.mp_small_int_bits + header[4] = 32 # qstr_win_size + merged_mpy.extend(header) + + bytecode = bytearray() + bytecode_len = 6 + len(raw_codes) * 4 + 2 + bytecode.append(bytecode_len << 2) # kind and length + bytecode.append(0b00000000) # signature prelude + bytecode.append(0b00001000) # size prelude + bytecode.extend(b'\x00\x01') # MP_QSTR_ + bytecode.extend(b'\x00\x01') # MP_QSTR_ + for idx in range(len(raw_codes)): + bytecode.append(0x32) # MP_BC_MAKE_FUNCTION + bytecode.append(idx) # index raw code + bytecode.extend(b'\x34\x00') # MP_BC_CALL_FUNCTION, 0 args + bytecode.extend(b'\x51\x63') # MP_BC_LOAD_NONE, MP_BC_RETURN_VALUE + + bytecode.append(0) # n_obj + bytecode.append(len(raw_codes)) # n_raw_code + + merged_mpy.extend(bytecode) + + for rc in raw_codes: + with open(rc.mpy_source_file, 'rb') as f: + f.read(4) # skip header + read_uint(f) # skip qstr_win_size + data = f.read() # read rest of mpy file + merged_mpy.extend(data) + + if output_file is None: + sys.stdout.buffer.write(merged_mpy) + else: + with open(output_file, 'wb') as f: + f.write(merged_mpy) + def main(): import argparse cmd_parser = argparse.ArgumentParser(description='A tool to work with MicroPython .mpy files.') @@ -796,12 +848,16 @@ def main(): help='dump contents of files') cmd_parser.add_argument('-f', '--freeze', action='store_true', help='freeze files') + cmd_parser.add_argument('--merge', action='store_true', + help='merge multiple .mpy files into one') cmd_parser.add_argument('-q', '--qstr-header', help='qstr header file to freeze against') cmd_parser.add_argument('-mlongint-impl', choices=['none', 'longlong', 'mpz'], default='mpz', help='long-int implementation used by target (default mpz)') cmd_parser.add_argument('-mmpz-dig-size', metavar='N', type=int, default=16, help='mpz digit size used by target (default 16)') + cmd_parser.add_argument('-o', '--output', default=None, + help='output file') cmd_parser.add_argument('files', nargs='+', help='input .mpy files') args = cmd_parser.parse_args() @@ -835,6 +891,8 @@ def main(): except FreezeError as er: print(er, file=sys.stderr) sys.exit(1) + elif args.merge: + merged_mpy = merge_mpy(raw_codes, args.output) if __name__ == '__main__': main() From aad79adab7285cbe1c1b975fcd490542fd3ab85c Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 28 Aug 2019 17:03:08 +1000 Subject: [PATCH 0764/1299] tools/mpy_ld.py: Add new mpy_ld.py tool and associated build files. This commit adds a new tool called mpy_ld.py which is essentially a linker that builds .mpy files directly from .o files. A new header file (dynruntime.h) and makefile fragment (dynruntime.mk) are also included which allow building .mpy files from C source code. Such .mpy files can then be dynamically imported as though they were a normal Python module, even though they are implemented in C. Converting .o files directly (rather than pre-linked .elf files) allows the resulting .mpy to be more efficient because it has more control over the relocations; for example it can skip PLT indirection. Doing it this way also allows supporting more architectures, such as Xtensa which has specific needs for position-independent code and the GOT. The tool supports targets of x86, x86-64, ARM Thumb and Xtensa (windowed and non-windowed). BSS, text and rodata sections are supported, with relocations to all internal sections and symbols, as well as relocations to some external symbols (defined by dynruntime.h), and linking of qstrs. --- py/dynruntime.h | 193 ++++++++++ py/dynruntime.mk | 134 +++++++ tools/mpy_ld.py | 978 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1305 insertions(+) create mode 100644 py/dynruntime.h create mode 100644 py/dynruntime.mk create mode 100755 tools/mpy_ld.py diff --git a/py/dynruntime.h b/py/dynruntime.h new file mode 100644 index 0000000000000..34cf6010c46fd --- /dev/null +++ b/py/dynruntime.h @@ -0,0 +1,193 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_PY_DYNRUNTIME_H +#define MICROPY_INCLUDED_PY_DYNRUNTIME_H + +// This header file contains definitions to dynamically implement the static +// MicroPython runtime API defined in py/obj.h and py/runtime.h. + +#include "py/nativeglue.h" +#include "py/objstr.h" + +#undef MP_ROM_QSTR +#undef MP_OBJ_QSTR_VALUE +#undef MP_OBJ_NEW_QSTR +#undef mp_const_none +#undef mp_const_false +#undef mp_const_true +#undef mp_const_empty_tuple +#undef nlr_raise + +/******************************************************************************/ +// Memory allocation + +#define m_malloc(n) (m_malloc_dyn((n))) +#define m_free(ptr) (m_free_dyn((ptr))) +#define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes))) + +static inline void *m_malloc_dyn(size_t n) { + // TODO won't raise on OOM + return mp_fun_table.realloc_(NULL, n, false); +} + +static inline void m_free_dyn(void *ptr) { + mp_fun_table.realloc_(ptr, 0, false); +} + +static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { + // TODO won't raise on OOM + return mp_fun_table.realloc_(ptr, new_num_bytes, true); +} + +/******************************************************************************/ +// Printing + +#define mp_plat_print (*mp_fun_table.plat_print) +#define mp_printf(p, ...) (mp_fun_table.printf_((p), __VA_ARGS__)) +#define mp_vprintf(p, fmt, args) (mp_fun_table.vprintf_((p), (fmt), (args))) + +/******************************************************************************/ +// Types and objects + +#define MP_OBJ_NEW_QSTR(x) MP_OBJ_NEW_QSTR_ ## x + +#define mp_type_type (*mp_fun_table.type_type) +#define mp_type_str (*mp_fun_table.type_str) +#define mp_type_list (*mp_fun_table.type_list) +#define mp_type_EOFError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_EOFError))) +#define mp_type_IndexError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_IndexError))) +#define mp_type_KeyError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_KeyError))) +#define mp_type_NotImplementedError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_NotImplementedError))) +#define mp_type_RuntimeError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_RuntimeError))) +#define mp_type_TypeError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_TypeError))) +#define mp_type_ValueError (*(mp_obj_type_t*)(mp_load_global(MP_QSTR_ValueError))) + +#define mp_stream_read_obj (*mp_fun_table.stream_read_obj) +#define mp_stream_readinto_obj (*mp_fun_table.stream_readinto_obj) +#define mp_stream_unbuffered_readline_obj (*mp_fun_table.stream_unbuffered_readline_obj) +#define mp_stream_write_obj (*mp_fun_table.stream_write_obj) + +#define mp_const_none ((mp_obj_t)mp_fun_table.const_none) +#define mp_const_false ((mp_obj_t)mp_fun_table.const_false) +#define mp_const_true ((mp_obj_t)mp_fun_table.const_true) +#define mp_const_empty_tuple (mp_fun_table.new_tuple(0, NULL)) + +#define mp_obj_new_bool(b) ((b) ? (mp_obj_t)mp_fun_table.const_true : (mp_obj_t)mp_fun_table.const_false) +#define mp_obj_new_int(i) (mp_fun_table.native_to_obj(i, MP_NATIVE_TYPE_INT)) +#define mp_obj_new_str(data, len) (mp_fun_table.obj_new_str((data), (len))) +#define mp_obj_new_str_of_type(t, d, l) (mp_obj_new_str_of_type_dyn((t), (d), (l))) +#define mp_obj_new_bytes(data, len) (mp_fun_table.obj_new_bytes((data), (len))) +#define mp_obj_new_bytearray_by_ref(n, i) (mp_fun_table.obj_new_bytearray_by_ref((n), (i))) +#define mp_obj_new_tuple(n, items) (mp_fun_table.new_tuple((n), (items))) +#define mp_obj_new_list(n, items) (mp_fun_table.new_list((n), (items))) + +#define mp_obj_get_type(o) (mp_fun_table.obj_get_type((o))) +#define mp_obj_get_int(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_INT)) +#define mp_obj_str_get_str(s) ((void*)mp_fun_table.native_from_obj(s, MP_NATIVE_TYPE_PTR)) +#define mp_obj_str_get_data(o, len) (mp_obj_str_get_data_dyn((o), (len))) +#define mp_get_buffer_raise(o, bufinfo, fl) (mp_fun_table.get_buffer_raise((o), (bufinfo), (fl))) +#define mp_get_stream_raise(s, flags) (mp_fun_table.get_stream_raise((s), (flags))) + +#define mp_obj_list_append(list, item) (mp_fun_table.list_append((list), (item))) + +static inline mp_obj_t mp_obj_new_str_of_type_dyn(const mp_obj_type_t *type, const byte* data, size_t len) { + if (type == &mp_type_str) { + return mp_obj_new_str((const char*)data, len); + } else { + return mp_obj_new_bytes(data, len); + } +} + +static inline void *mp_obj_str_get_data_dyn(mp_obj_t o, size_t *l) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(o, &bufinfo, MP_BUFFER_READ); + *l = bufinfo.len; + return bufinfo.buf; +} + +/******************************************************************************/ +// General runtime functions + +#define mp_load_name(qst) (mp_fun_table.load_name(qst)) +#define mp_load_global(qst) (mp_fun_table.load_global(qst)) +#define mp_store_global(qst, obj) (mp_fun_table.store_global((qst), (obj))) +#define mp_unary_op(op, obj) (mp_fun_table.unary_op((op), (obj))) +#define mp_binary_op(op, lhs, rhs) (mp_fun_table.binary_op((op), (lhs), (rhs))) + +#define mp_make_function_from_raw_code(rc, def_args, def_kw_args) \ + (mp_fun_table.make_function_from_raw_code((rc), (def_args), (def_kw_args))) + +#define mp_call_function_n_kw(fun, n_args, n_kw, args) \ + (mp_fun_table.call_function_n_kw((fun), (n_args) | ((n_kw) << 8), args)) + +#define mp_arg_check_num(n_args, n_kw, n_args_min, n_args_max, takes_kw) \ + (mp_fun_table.arg_check_num_sig((n_args), (n_kw), MP_OBJ_FUN_MAKE_SIG((n_args_min), (n_args_max), (takes_kw)))) + +#define MP_DYNRUNTIME_INIT_ENTRY \ + mp_obj_t old_globals = mp_fun_table.swap_globals(self->globals); \ + mp_raw_code_t rc; \ + rc.kind = MP_CODE_NATIVE_VIPER; \ + rc.scope_flags = 0; \ + rc.const_table = (void*)self->const_table; \ + (void)rc; + +#define MP_DYNRUNTIME_INIT_EXIT \ + mp_fun_table.swap_globals(old_globals); \ + return mp_const_none; + +#define MP_DYNRUNTIME_MAKE_FUNCTION(f) \ + (mp_make_function_from_raw_code((rc.fun_data = (f), &rc), MP_OBJ_NULL, MP_OBJ_NULL)) + +/******************************************************************************/ +// Exceptions + +#define mp_obj_new_exception(o) ((mp_obj_t)(o)) // Assumes returned object will be raised, will create instance then +#define mp_obj_new_exception_arg1(e_type, arg) (mp_obj_new_exception_arg1_dyn((e_type), (arg))) + +#define nlr_raise(o) (mp_raise_dyn(o)) +#define mp_raise_msg(type, msg) (mp_fun_table.raise_msg((type), (msg))) +#define mp_raise_OSError(er) (mp_raise_OSError_dyn(er)) +#define mp_raise_NotImplementedError(msg) (mp_raise_msg(&mp_type_NotImplementedError, (msg))) +#define mp_raise_TypeError(msg) (mp_raise_msg(&mp_type_TypeError, (msg))) +#define mp_raise_ValueError(msg) (mp_raise_msg(&mp_type_ValueError, (msg))) + +static inline mp_obj_t mp_obj_new_exception_arg1_dyn(const mp_obj_type_t *exc_type, mp_obj_t arg) { + mp_obj_t args[1] = { arg }; + return mp_call_function_n_kw(MP_OBJ_FROM_PTR(exc_type), 1, 0, &args[0]); +} + +static NORETURN inline void mp_raise_dyn(mp_obj_t o) { + mp_fun_table.raise(o); + for (;;) { + } +} + +static inline void mp_raise_OSError_dyn(int er) { + mp_obj_t args[1] = { MP_OBJ_NEW_SMALL_INT(er) }; + nlr_raise(mp_call_function_n_kw(mp_load_global(MP_QSTR_OSError), 1, 0, &args[0])); +} + +#endif // MICROPY_INCLUDED_PY_DYNRUNTIME_H diff --git a/py/dynruntime.mk b/py/dynruntime.mk new file mode 100644 index 0000000000000..b01b80e0dd8c2 --- /dev/null +++ b/py/dynruntime.mk @@ -0,0 +1,134 @@ +# Makefile fragment for generating native .mpy files from C source +# MPY_DIR must be set to the top of the MicroPython source tree + +BUILD ?= build + +ECHO = @echo +RM = /bin/rm +MKDIR = /bin/mkdir +PYTHON = python3 +MPY_CROSS = $(MPY_DIR)/mpy-cross/mpy-cross +MPY_TOOL = $(PYTHON) $(MPY_DIR)/tools/mpy-tool.py +MPY_LD = $(PYTHON) $(MPY_DIR)/tools/mpy_ld.py + +Q = @ +ifeq ("$(origin V)", "command line") +ifeq ($(V),1) +Q = +MPY_LD += '-vvv' +endif +endif + +ARCH_UPPER = $(shell echo $(ARCH) | tr '[:lower:]' '[:upper:]') +CONFIG_H = $(BUILD)/$(MOD).config.h + +CFLAGS += -I. -I$(MPY_DIR) +CFLAGS += -std=c99 +CFLAGS += -Os +CFLAGS += -Wall -Werror -DNDEBUG +CFLAGS += -DNO_QSTR +CFLAGS += -DMP_CONFIGFILE='<$(CONFIG_H)>' +CFLAGS += -fpic -fno-common +CFLAGS += -U _FORTIFY_SOURCE # prevent use of __*_chk libc functions +#CFLAGS += -fdata-sections -ffunction-sections + +MPY_CROSS_FLAGS += -march=$(ARCH) + +SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC)))) +SRC_MPY += $(addprefix $(BUILD)/, $(patsubst %.py,%.mpy,$(filter %.py,$(SRC)))) + +################################################################################ +# Architecture configuration + +ifeq ($(ARCH),x86) + +# x86 +CROSS = +CFLAGS += -m32 -fno-stack-protector +MPY_CROSS_FLAGS += -mcache-lookup-bc + +else ifeq ($(ARCH),x64) + +# x64 +CROSS = +CFLAGS += -fno-stack-protector +MPY_CROSS_FLAGS += -mcache-lookup-bc + +else ifeq ($(ARCH),armv7m) + +# thumb +CROSS = arm-none-eabi- +CFLAGS += -mthumb -mcpu=cortex-m3 + +else ifeq ($(ARCH),armv7emsp) + +# thumb +CROSS = arm-none-eabi- +CFLAGS += -mthumb -mcpu=cortex-m4 +CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard + +else ifeq ($(ARCH),armv7emdp) + +# thumb +CROSS = arm-none-eabi- +CFLAGS += -mthumb -mcpu=cortex-m7 +CFLAGS += -mfpu=fpv5-d16 -mfloat-abi=hard + +else ifeq ($(ARCH),xtensa) + +# xtensa +CROSS = xtensa-lx106-elf- +CFLAGS += -mforce-l32 + +else ifeq ($(ARCH),xtensawin) + +# xtensawin +CROSS = xtensa-esp32-elf- +CFLAGS += + +else +$(error architecture '$(ARCH)' not supported) +endif + +CFLAGS += $(CFLAGS_EXTRA) + +################################################################################ +# Build rules + +.PHONY: all clean + +all: $(MOD).mpy + +clean: + $(RM) -rf $(BUILD) $(CLEAN_EXTRA) + +# Create build destination directories first +BUILD_DIRS = $(sort $(dir $(CONFIG_H) $(SRC_O) $(SRC_MPY))) +$(CONFIG_H) $(SRC_O) $(SRC_MPY): | $(BUILD_DIRS) +$(BUILD_DIRS): + $(Q)$(MKDIR) -p $@ + +# Preprocess all source files to generate $(CONFIG_H) +$(CONFIG_H): $(SRC) + $(ECHO) "GEN $@" + $(Q)$(MPY_LD) --arch $(ARCH) --preprocess -o $@ $^ + +# Build .o from .c source files +$(BUILD)/%.o: %.c $(CONFIG_H) Makefile + $(ECHO) "CC $<" + $(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $< + +# Build .mpy from .py source files +$(BUILD)/%.mpy: %.py + $(ECHO) "MPY $<" + $(Q)$(MPY_CROSS) $(MPY_CROSS_FLAGS) -o $@ $< + +# Build native .mpy from object files +$(BUILD)/$(MOD).native.mpy: $(SRC_O) + $(ECHO) "LINK $<" + $(Q)$(MPY_LD) --arch $(ARCH) --qstrs $(CONFIG_H) -o $@ $^ + +# Build final .mpy from all intermediate .mpy files +$(MOD).mpy: $(BUILD)/$(MOD).native.mpy $(SRC_MPY) + $(ECHO) "GEN $@" + $(Q)$(MPY_TOOL) --merge -o $@ $^ diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py new file mode 100755 index 0000000000000..07105caac9694 --- /dev/null +++ b/tools/mpy_ld.py @@ -0,0 +1,978 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2019 Damien P. George +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +""" +Link .o files to .mpy +""" + +import sys, os, struct, re +from elftools.elf import elffile + +sys.path.append(os.path.dirname(__file__) + '/../py') +import makeqstrdata as qstrutil + +# MicroPython constants +MPY_VERSION = 5 +MP_NATIVE_ARCH_X86 = 1 +MP_NATIVE_ARCH_X64 = 2 +MP_NATIVE_ARCH_ARMV7M = 5 +MP_NATIVE_ARCH_ARMV7EMSP = 7 +MP_NATIVE_ARCH_ARMV7EMDP = 8 +MP_NATIVE_ARCH_XTENSA = 9 +MP_NATIVE_ARCH_XTENSAWIN = 10 +MP_CODE_BYTECODE = 2 +MP_CODE_NATIVE_VIPER = 4 +MP_SCOPE_FLAG_VIPERRELOC = 0x10 +MP_SCOPE_FLAG_VIPERRODATA = 0x20 +MP_SCOPE_FLAG_VIPERBSS = 0x40 +MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE = 1 +MICROPY_PY_BUILTINS_STR_UNICODE = 2 +MP_SMALL_INT_BITS = 31 +QSTR_WINDOW_SIZE = 32 + +# ELF constants +R_386_32 = 1 +R_X86_64_64 = 1 +R_XTENSA_32 = 1 +R_386_PC32 = 2 +R_X86_64_PC32 = 2 +R_ARM_ABS32 = 2 +R_386_GOT32 = 3 +R_ARM_REL32 = 3 +R_386_PLT32 = 4 +R_X86_64_PLT32 = 4 +R_XTENSA_PLT = 6 +R_386_GOTOFF = 9 +R_386_GOTPC = 10 +R_ARM_THM_CALL = 10 +R_XTENSA_DIFF32 = 19 +R_XTENSA_SLOT0_OP = 20 +R_ARM_BASE_PREL = 25 # aka R_ARM_GOTPC +R_ARM_GOT_BREL = 26 # aka R_ARM_GOT32 +R_ARM_THM_JUMP24 = 30 +R_X86_64_REX_GOTPCRELX = 42 +R_386_GOT32X = 43 + +################################################################################ +# Architecture configuration + +def asm_jump_x86(entry): + return struct.pack('> 11 == 0 or b_off >> 11 == -1: + # Signed value fits in 12 bits + b0 = 0xe000 | (b_off >> 1 & 0x07ff) + b1 = 0 + else: + # Use large jump + b0 = 0xf000 | (b_off >> 12 & 0x07ff) + b1 = 0xb800 | (b_off >> 1 & 0x7ff) + return struct.pack('> 8) + +class ArchData: + def __init__(self, name, mpy_feature, qstr_entry_size, word_size, arch_got, asm_jump): + self.name = name + self.mpy_feature = mpy_feature + self.qstr_entry_size = qstr_entry_size + self.word_size = word_size + self.arch_got = arch_got + self.asm_jump = asm_jump + self.separate_rodata = name == 'EM_XTENSA' and qstr_entry_size == 4 + +ARCH_DATA = { + 'x86': ArchData( + 'EM_386', + MP_NATIVE_ARCH_X86 << 2 | MICROPY_PY_BUILTINS_STR_UNICODE | MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE, + 2, 4, (R_386_PC32, R_386_GOT32, R_386_GOT32X), asm_jump_x86, + ), + 'x64': ArchData( + 'EM_X86_64', + MP_NATIVE_ARCH_X64 << 2 | MICROPY_PY_BUILTINS_STR_UNICODE | MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE, + 2, 8, (R_X86_64_REX_GOTPCRELX,), asm_jump_x86, + ), + 'armv7m': ArchData( + 'EM_ARM', + MP_NATIVE_ARCH_ARMV7M << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, + 2, 4, (R_ARM_GOT_BREL,), asm_jump_arm, + ), + 'armv7emsp': ArchData( + 'EM_ARM', + MP_NATIVE_ARCH_ARMV7EMSP << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, + 2, 4, (R_ARM_GOT_BREL,), asm_jump_arm, + ), + 'armv7emdp': ArchData( + 'EM_ARM', + MP_NATIVE_ARCH_ARMV7EMDP << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, + 2, 4, (R_ARM_GOT_BREL,), asm_jump_arm, + ), + 'xtensa': ArchData( + 'EM_XTENSA', + MP_NATIVE_ARCH_XTENSA << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, + 2, 4, (R_XTENSA_32, R_XTENSA_PLT), asm_jump_xtensa, + ), + 'xtensawin': ArchData( + 'EM_XTENSA', + MP_NATIVE_ARCH_XTENSAWIN << 2 | MICROPY_PY_BUILTINS_STR_UNICODE, + 4, 4, (R_XTENSA_32, R_XTENSA_PLT), asm_jump_xtensa, + ), +} + +################################################################################ +# Helper functions + +def align_to(value, align): + return (value + align - 1) & ~(align - 1) + +def unpack_u24le(data, offset): + return data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 + +def pack_u24le(data, offset, value): + data[offset] = value & 0xff + data[offset + 1] = value >> 8 & 0xff + data[offset + 2] = value >> 16 & 0xff + +def xxd(text): + for i in range(0, len(text), 16): + print('{:08x}:'.format(i), end='') + for j in range(4): + off = i + j * 4 + if off < len(text): + d = int.from_bytes(text[off:off + 4], 'little') + print(' {:08x}'.format(d), end='') + print() + +# Smaller numbers are enabled first +LOG_LEVEL_1 = 1 +LOG_LEVEL_2 = 2 +LOG_LEVEL_3 = 3 +log_level = LOG_LEVEL_1 + +def log(level, msg): + if level <= log_level: + print(msg) + +################################################################################ +# Qstr extraction + +def extract_qstrs(source_files): + def read_qstrs(f): + with open(f) as f: + vals = set() + objs = set() + for line in f: + while line: + m = re.search(r'MP_OBJ_NEW_QSTR\((MP_QSTR_[A-Za-z0-9_]*)\)', line) + if m: + objs.add(m.group(1)) + else: + m = re.search(r'MP_QSTR_[A-Za-z0-9_]*', line) + if m: + vals.add(m.group()) + if m: + s = m.span() + line = line[:s[0]] + line[s[1]:] + else: + line = '' + return vals, objs + + static_qstrs = ['MP_QSTR_' + qstrutil.qstr_escape(q) for q in qstrutil.static_qstr_list] + + qstr_vals = set() + qstr_objs = set() + for f in source_files: + vals, objs = read_qstrs(f) + qstr_vals.update(vals) + qstr_objs.update(objs) + qstr_vals.difference_update(static_qstrs) + + return static_qstrs, qstr_vals, qstr_objs + +################################################################################ +# Linker + +class LinkError(Exception): + pass + +class Section: + def __init__(self, name, data, alignment, filename=None): + self.filename = filename + self.name = name + self.data = data + self.alignment = alignment + self.addr = 0 + self.reloc = [] + + @staticmethod + def from_elfsec(elfsec, filename): + assert elfsec.header.sh_addr == 0 + return Section(elfsec.name, elfsec.data(), elfsec.data_alignment, filename) + +class GOTEntry: + def __init__(self, name, sym, link_addr=0): + self.name = name + self.sym = sym + self.offset = None + self.link_addr = link_addr + + def isexternal(self): + return self.sec_name.startswith('.external') + + def istext(self): + return self.sec_name.startswith('.text') + + def isrodata(self): + return self.sec_name.startswith(('.rodata', '.data.rel.ro')) + + def isbss(self): + return self.sec_name.startswith('.bss') + +class LiteralEntry: + def __init__(self, value, offset): + self.value = value + self.offset = offset + +class LinkEnv: + def __init__(self, arch): + self.arch = ARCH_DATA[arch] + self.sections = [] # list of sections in order of output + self.literal_sections = [] # list of literal sections (xtensa only) + self.known_syms = {} # dict of symbols that are defined + self.unresolved_syms = [] # list of unresolved symbols + self.mpy_relocs = [] # list of relocations needed in the output .mpy file + + def check_arch(self, arch_name): + if arch_name != self.arch.name: + raise LinkError('incompatible arch') + + def print_sections(self): + log(LOG_LEVEL_2, 'sections:') + for sec in self.sections: + log(LOG_LEVEL_2, ' {:08x} {} size={}'.format(sec.addr, sec.name, len(sec.data))) + + def find_addr(self, name): + if name in self.known_syms: + s = self.known_syms[name] + return s.section.addr + s['st_value'] + raise LinkError('unknown symbol: {}'.format(name)) + +def build_got_generic(env): + env.got_entries = {} + for sec in env.sections: + for r in sec.reloc: + s = r.sym + if not (s.entry['st_info']['bind'] == 'STB_GLOBAL' and r['r_info_type'] in env.arch.arch_got): + continue + s_type = s.entry['st_info']['type'] + assert s_type in ('STT_NOTYPE', 'STT_FUNC', 'STT_OBJECT'), s_type + assert s.name + if s.name in env.got_entries: + continue + env.got_entries[s.name] = GOTEntry(s.name, s) + +def build_got_xtensa(env): + env.got_entries = {} + env.lit_entries = {} + env.xt_literals = {} + + # Extract the values from the literal table + for sec in env.literal_sections: + assert len(sec.data) % env.arch.word_size == 0 + + # Look through literal relocations to find any global pointers that should be GOT entries + for r in sec.reloc: + s = r.sym + s_type = s.entry['st_info']['type'] + assert s_type in ('STT_NOTYPE', 'STT_FUNC', 'STT_OBJECT', 'STT_SECTION'), s_type + assert r['r_info_type'] in env.arch.arch_got + assert r['r_offset'] % env.arch.word_size == 0 + # This entry is a global pointer + existing = struct.unpack_from(' {}+{:08x}'.format(g.offset, g.name, g.sec_name, g.link_addr)) + +def populate_lit(env): + log(LOG_LEVEL_2, 'LIT: {:08x}'.format(env.lit_section.addr)) + for lit_entry in env.lit_entries.values(): + value = lit_entry.value + log(LOG_LEVEL_2, ' {:08x} = {:08x}'.format(lit_entry.offset, value)) + o = env.lit_section.addr + lit_entry.offset + env.full_text[o:o + env.arch.word_size] = value.to_bytes(env.arch.word_size, 'little') + +def do_relocation_text(env, text_addr, r): + # Extract relevant info about symbol that's being relocated + s = r.sym + s_bind = s.entry['st_info']['bind'] + s_shndx = s.entry['st_shndx'] + s_type = s.entry['st_info']['type'] + r_offset = r['r_offset'] + text_addr + r_info_type = r['r_info_type'] + try: + # only for RELA sections + r_addend = r['r_addend'] + except KeyError: + r_addend = 0 + + # Default relocation type and name for logging + reloc_type = 'le32' + log_name = None + + if (env.arch.name == 'EM_386' and r_info_type in (R_386_PC32, R_386_PLT32) + or env.arch.name == 'EM_X86_64' and r_info_type in (R_X86_64_PC32, R_X86_64_PLT32) + or env.arch.name == 'EM_ARM' and r_info_type in (R_ARM_REL32, R_ARM_THM_CALL, R_ARM_THM_JUMP24) + or s_bind == 'STB_LOCAL' and env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_32 # not GOT + ): + # Standard relocation to fixed location within text/rodata + if hasattr(s, 'resolved'): + s = s.resolved + + sec = s.section + + if env.arch.separate_rodata and sec.name.startswith('.rodata'): + raise LinkError('fixed relocation to rodata with rodata referenced via GOT') + + if sec.name.startswith('.bss'): + raise LinkError('{}: fixed relocation to bss (bss variables can\'t be static)'.format(s.filename)) + + if sec.name.startswith('.external'): + raise LinkError('{}: fixed relocation to external symbol: {}'.format(s.filename, s.name)) + + addr = sec.addr + s['st_value'] + reloc = addr - r_offset + r_addend + + if r_info_type in (R_ARM_THM_CALL, R_ARM_THM_JUMP24): + # Both relocations have the same bit pattern to rewrite: + # R_ARM_THM_CALL: bl + # R_ARM_THM_JUMP24: b.w + reloc_type = 'thumb_b' + + elif (env.arch.name == 'EM_386' and r_info_type == R_386_GOTPC + or env.arch.name == 'EM_ARM' and r_info_type == R_ARM_BASE_PREL + ): + # Relocation to GOT address itself + assert s.name == '_GLOBAL_OFFSET_TABLE_' + addr = env.got_section.addr + reloc = addr - r_offset + r_addend + + elif (env.arch.name == 'EM_386' and r_info_type in (R_386_GOT32, R_386_GOT32X) + or env.arch.name == 'EM_ARM' and r_info_type == R_ARM_GOT_BREL + ): + # Relcation pointing to GOT + reloc = addr = env.got_entries[s.name].offset + + elif env.arch.name == 'EM_X86_64' and r_info_type == R_X86_64_REX_GOTPCRELX: + # Relcation pointing to GOT + got_entry = env.got_entries[s.name] + addr = env.got_section.addr + got_entry.offset + reloc = addr - r_offset + r_addend + + elif env.arch.name == 'EM_386' and r_info_type == R_386_GOTOFF: + # Relocation relative to GOT + addr = s.section.addr + s['st_value'] + reloc = addr - env.got_section.addr + r_addend + + elif env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_SLOT0_OP: + # Relocation pointing to GOT, xtensa specific + sec = s.section + if sec.name.startswith('.text'): + # it looks like R_XTENSA_SLOT0_OP into .text is already correctly relocated + return + assert sec.name.startswith('.literal'), sec.name + lit_idx = '{}+0x{:x}'.format(sec.filename, r_addend) + lit_ptr = env.xt_literals[lit_idx] + if isinstance(lit_ptr, str): + addr = env.got_section.addr + env.got_entries[lit_ptr].offset + log_name = 'GOT {}'.format(lit_ptr) + else: + addr = env.lit_section.addr + env.lit_entries[lit_ptr].offset + log_name = 'LIT' + reloc = addr - r_offset + reloc_type = 'xtensa_l32r' + + elif env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_DIFF32: + if s.section.name.startswith('.text'): + # it looks like R_XTENSA_DIFF32 into .text is already correctly relocated + return + assert 0 + + else: + # Unknown/unsupported relocation + assert 0, r_info_type + + # Write relocation + if reloc_type == 'le32': + existing, = struct.unpack_from('= 0x400000: # 2's complement + existing -= 0x800000 + new = existing + reloc + b_h = (b_h & 0xf800) | (new >> 12) & 0x7ff + b_l = (b_l & 0xf800) | (new >> 1) & 0x7ff + struct.pack_into('> 8 + l32r_imm16 = (l32r_imm16 + reloc >> 2) & 0xffff + l32r = l32r & 0xff | l32r_imm16 << 8 + pack_u24le(env.full_text, r_offset, l32r) + else: + assert 0, reloc_type + + # Log information about relocation + if log_name is None: + if s_type == 'STT_SECTION': + log_name = s.section.name + else: + log_name = s.name + log(LOG_LEVEL_3, ' {:08x} {} -> {:08x}'.format(r_offset, log_name, addr)) + +def do_relocation_data(env, text_addr, r): + s = r.sym + s_type = s.entry['st_info']['type'] + r_offset = r['r_offset'] + text_addr + r_info_type = r['r_info_type'] + try: + # only for RELA sections + r_addend = r['r_addend'] + except KeyError: + r_addend = 0 + + if (env.arch.name == 'EM_386' and r_info_type == R_386_32 + or env.arch.name == 'EM_X86_64' and r_info_type == R_X86_64_64 + or env.arch.name == 'EM_ARM' and r_info_type == R_ARM_ABS32 + or env.arch.name == 'EM_XTENSA' and r_info_type == R_XTENSA_32): + # Relocation in data.rel.ro to internal/external symbol + if env.arch.word_size == 4: + struct_type = ' {} {:08x}'.format(r_offset, log_name, addr)) + if env.arch.separate_rodata: + data = env.full_rodata + else: + data = env.full_text + existing, = struct.unpack_from(struct_type, data, r_offset) + if sec.name.startswith(('.text', '.rodata', '.data.rel.ro', '.bss')): + struct.pack_into(struct_type, data, r_offset, existing + addr) + kind = sec.name + elif sec.name == '.external.mp_fun_table': + assert addr == 0 + kind = s.mp_fun_table_offset + else: + assert 0, sec.name + if env.arch.separate_rodata: + base = '.rodata' + else: + base = '.text' + env.mpy_relocs.append((base, r_offset, kind)) + + else: + # Unknown/unsupported relocation + assert 0, r_info_type + +def load_object_file(env, felf): + with open(felf, 'rb') as f: + elf = elffile.ELFFile(f) + env.check_arch(elf['e_machine']) + + # Get symbol table + symtab = list(elf.get_section_by_name('.symtab').iter_symbols()) + + # Load needed sections from ELF file + sections_shndx = {} # maps elf shndx to Section object + for idx, s in enumerate(elf.iter_sections()): + if s.header.sh_type in ('SHT_PROGBITS', 'SHT_NOBITS'): + if s.data_size == 0: + # Ignore empty sections + pass + elif s.name.startswith(('.literal', '.text', '.rodata', '.data.rel.ro', '.bss')): + sec = Section.from_elfsec(s, felf) + sections_shndx[idx] = sec + if s.name.startswith('.literal'): + env.literal_sections.append(sec) + else: + env.sections.append(sec) + elif s.name.startswith('.data'): + raise LinkError('{}: {} non-empty'.format(felf, s.name)) + else: + # Ignore section + pass + elif s.header.sh_type in ('SHT_REL', 'SHT_RELA'): + shndx = s.header.sh_info + if shndx in sections_shndx: + sec = sections_shndx[shndx] + sec.reloc_name = s.name + sec.reloc = list(s.iter_relocations()) + for r in sec.reloc: + r.sym = symtab[r['r_info_sym']] + + # Link symbols to their sections, and update known and unresolved symbols + for sym in symtab: + sym.filename = felf + shndx = sym.entry['st_shndx'] + if shndx in sections_shndx: + # Symbol with associated section + sym.section = sections_shndx[shndx] + if sym['st_info']['bind'] == 'STB_GLOBAL': + # Defined global symbol + if sym.name in env.known_syms and not sym.name.startswith('__x86.get_pc_thunk.'): + raise LinkError('duplicate symbol: {}'.format(sym.name)) + env.known_syms[sym.name] = sym + elif sym.entry['st_shndx'] == 'SHN_UNDEF' and sym['st_info']['bind'] == 'STB_GLOBAL': + # Undefined global symbol, needs resolving + env.unresolved_syms.append(sym) + +def link_objects(env, native_qstr_vals_len, native_qstr_objs_len): + # Build GOT information + if env.arch.name == 'EM_XTENSA': + build_got_xtensa(env) + else: + build_got_generic(env) + + # Creat GOT section + got_size = len(env.got_entries) * env.arch.word_size + env.got_section = Section('GOT', bytearray(got_size), env.arch.word_size) + if env.arch.name == 'EM_XTENSA': + env.sections.insert(0, env.got_section) + else: + env.sections.append(env.got_section) + + # Create optional literal section + if env.arch.name == 'EM_XTENSA': + lit_size = len(env.lit_entries) * env.arch.word_size + env.lit_section = Section('LIT', bytearray(lit_size), env.arch.word_size) + env.sections.insert(1, env.lit_section) + + # Create section to contain mp_native_qstr_val_table + env.qstr_val_section = Section('.text.QSTR_VAL', bytearray(native_qstr_vals_len * env.arch.qstr_entry_size), env.arch.qstr_entry_size) + env.sections.append(env.qstr_val_section) + + # Create section to contain mp_native_qstr_obj_table + env.qstr_obj_section = Section('.text.QSTR_OBJ', bytearray(native_qstr_objs_len * env.arch.word_size), env.arch.word_size) + env.sections.append(env.qstr_obj_section) + + # Resolve unknown symbols + mp_fun_table_sec = Section('.external.mp_fun_table', b'', 0) + fun_table = {key: 63 + idx + for idx, key in enumerate([ + 'mp_type_type', + 'mp_type_str', + 'mp_type_list', + 'mp_type_dict', + 'mp_type_fun_builtin_0', + 'mp_type_fun_builtin_1', + 'mp_type_fun_builtin_2', + 'mp_type_fun_builtin_3', + 'mp_type_fun_builtin_var', + 'mp_stream_read_obj', + 'mp_stream_readinto_obj', + 'mp_stream_unbuffered_readline_obj', + 'mp_stream_write_obj', + ]) + } + for sym in env.unresolved_syms: + assert sym['st_value'] == 0 + if sym.name == '_GLOBAL_OFFSET_TABLE_': + pass + elif sym.name == 'mp_fun_table': + sym.section = Section('.external', b'', 0) + elif sym.name == 'mp_native_qstr_val_table': + sym.section = env.qstr_val_section + elif sym.name == 'mp_native_qstr_obj_table': + sym.section = env.qstr_obj_section + elif sym.name in env.known_syms: + sym.resolved = env.known_syms[sym.name] + else: + if sym.name in fun_table: + sym.section = mp_fun_table_sec + sym.mp_fun_table_offset = fun_table[sym.name] + else: + raise LinkError('{}: undefined symbol: {}'.format(sym.filename, sym.name)) + + # Align sections, assign their addresses, and create full_text + env.full_text = bytearray(env.arch.asm_jump(8)) # dummy, to be filled in later + env.full_rodata = bytearray(0) + env.full_bss = bytearray(0) + for sec in env.sections: + if env.arch.separate_rodata and sec.name.startswith(('.rodata', '.data.rel.ro')): + data = env.full_rodata + elif sec.name.startswith('.bss'): + data = env.full_bss + else: + data = env.full_text + sec.addr = align_to(len(data), sec.alignment) + data.extend(b'\x00' * (sec.addr - len(data))) + data.extend(sec.data) + + env.print_sections() + + populate_got(env) + if env.arch.name == 'EM_XTENSA': + populate_lit(env) + + # Fill in relocations + for sec in env.sections: + if not sec.reloc: + continue + log(LOG_LEVEL_3, '{}: {} relocations via {}:'.format(sec.filename, sec.name, sec.reloc_name)) + for r in sec.reloc: + if sec.name.startswith(('.text', '.rodata')): + do_relocation_text(env, sec.addr, r) + elif sec.name.startswith('.data.rel.ro'): + do_relocation_data(env, sec.addr, r) + else: + assert 0, sec.name + +################################################################################ +# .mpy output + +class MPYOutput: + def open(self, fname): + self.f = open(fname, 'wb') + self.prev_base = -1 + self.prev_offset = -1 + + def close(self): + self.f.close() + + def write_bytes(self, buf): + self.f.write(buf) + + def write_uint(self, val): + b = bytearray() + b.insert(0, val & 0x7f) + val >>= 7 + while val: + b.insert(0, 0x80 | (val & 0x7f)) + val >>= 7 + self.write_bytes(b) + + def write_qstr(self, s): + if s in qstrutil.static_qstr_list: + self.write_bytes(bytes([0, qstrutil.static_qstr_list.index(s) + 1])) + else: + s = bytes(s, 'ascii') + self.write_uint(len(s) << 1) + self.write_bytes(s) + + def write_obj(self, o): + if o is Ellipsis: + self.write_bytes(b'e') + return + else: + # Other Python types not implemented + assert 0 + + def write_reloc(self, base, offset, dest, n): + need_offset = not (base == self.prev_base and offset == self.prev_offset + 1) + self.prev_offset = offset + n - 1 + if dest <= 2: + dest = (dest << 1) | (n > 1) + else: + assert 6 <= dest <= 127 + assert n == 1 + dest = dest << 1 | need_offset + assert 0 <= dest <= 0xfe, dest + self.write_bytes(bytes([dest])) + if need_offset: + if base == '.text': + base = 0 + elif base == '.rodata': + base = 1 + self.write_uint(offset << 1 | base) + if n > 1: + self.write_uint(n) + +def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): + # Write jump instruction to start of text + jump = env.arch.asm_jump(entry_offset) + env.full_text[:len(jump)] = jump + + log(LOG_LEVEL_1, 'arch: {}'.format(env.arch.name)) + log(LOG_LEVEL_1, 'text size: {}'.format(len(env.full_text))) + if len(env.full_rodata): + log(LOG_LEVEL_1, 'rodata size: {}'.format(len(env.full_rodata))) + log(LOG_LEVEL_1, 'bss size: {}'.format(len(env.full_bss))) + log(LOG_LEVEL_1, 'GOT entries: {}'.format(len(env.got_entries))) + + #xxd(env.full_text) + + out = MPYOutput() + out.open(fmpy) + + # MPY: header + out.write_bytes(bytearray([ + ord('M'), + MPY_VERSION, + env.arch.mpy_feature, + MP_SMALL_INT_BITS, + QSTR_WINDOW_SIZE, + ])) + + # MPY: kind/len + out.write_uint(len(env.full_text) << 2 | (MP_CODE_NATIVE_VIPER - MP_CODE_BYTECODE)) + + # MPY: machine code + out.write_bytes(env.full_text) + + # MPY: n_qstr_link (assumes little endian) + out.write_uint(len(native_qstr_vals) + len(native_qstr_objs)) + for q in range(len(native_qstr_vals)): + off = env.qstr_val_section.addr + q * env.arch.qstr_entry_size + out.write_uint(off << 2) + out.write_qstr(native_qstr_vals[q]) + for q in range(len(native_qstr_objs)): + off = env.qstr_obj_section.addr + q * env.arch.word_size + out.write_uint(off << 2 | 3) + out.write_qstr(native_qstr_objs[q]) + + # MPY: scope_flags + scope_flags = MP_SCOPE_FLAG_VIPERRELOC + if len(env.full_rodata): + scope_flags |= MP_SCOPE_FLAG_VIPERRODATA + if len(env.full_bss): + scope_flags |= MP_SCOPE_FLAG_VIPERBSS + out.write_uint(scope_flags) + + # MPY: n_obj + out.write_uint(bool(len(env.full_rodata)) + bool(len(env.full_bss))) + + # MPY: n_raw_code + out.write_uint(0) + + # MPY: optional bytes object with rodata + if len(env.full_rodata): + out.write_obj(Ellipsis) + if len(env.full_bss): + out.write_obj(Ellipsis) + + # MPY: rodata and/or bss + if len(env.full_rodata): + rodata_const_table_idx = 1 + out.write_uint(len(env.full_rodata)) + out.write_bytes(env.full_rodata) + if len(env.full_bss): + bss_const_table_idx = bool(env.full_rodata) + 1 + out.write_uint(len(env.full_bss)) + + # MPY: relocation information + prev_kind = None + for base, addr, kind in env.mpy_relocs: + if isinstance(kind, str) and kind.startswith('.text'): + kind = 0 + elif kind in ('.rodata', '.data.rel.ro'): + if env.arch.separate_rodata: + kind = rodata_const_table_idx + else: + kind = 0 + elif isinstance(kind, str) and kind.startswith('.bss'): + kind = bss_const_table_idx + elif kind == 'mp_fun_table': + kind = 6 + else: + kind = 7 + kind + assert addr % env.arch.word_size == 0, addr + offset = addr // env.arch.word_size + if kind == prev_kind and base == prev_base and offset == prev_offset + 1: + prev_n += 1 + prev_offset += 1 + else: + if prev_kind is not None: + out.write_reloc(prev_base, prev_offset - prev_n + 1, prev_kind, prev_n) + prev_kind = kind + prev_base = base + prev_offset = offset + prev_n = 1 + if prev_kind is not None: + out.write_reloc(prev_base, prev_offset - prev_n + 1, prev_kind, prev_n) + + # MPY: sentinel for end of relocations + out.write_bytes(b'\xff') + + out.close() + +################################################################################ +# main + +def do_preprocess(args): + if args.output is None: + assert args.files[0].endswith('.c') + args.output = args.files[0][:-1] + 'config.h' + static_qstrs, qstr_vals, qstr_objs = extract_qstrs(args.files) + with open(args.output, 'w') as f: + print('#include \n' + 'typedef uintptr_t mp_uint_t;\n' + 'typedef intptr_t mp_int_t;\n' + 'typedef uintptr_t mp_off_t;', file=f) + for i, q in enumerate(static_qstrs): + print('#define %s (%u)' % (q, i + 1), file=f) + for i, q in enumerate(sorted(qstr_vals)): + print('#define %s (mp_native_qstr_val_table[%d])' % (q, i), file=f) + for i, q in enumerate(sorted(qstr_objs)): + print('#define MP_OBJ_NEW_QSTR_%s ((mp_obj_t)mp_native_qstr_obj_table[%d])' % (q, i), file=f) + if args.arch == 'xtensawin': + qstr_type = 'uint32_t' # esp32 can only read 32-bit values from IRAM + else: + qstr_type = 'uint16_t' + print('extern const {} mp_native_qstr_val_table[];'.format(qstr_type), file=f) + print('extern const mp_uint_t mp_native_qstr_obj_table[];', file=f) + +def do_link(args): + if args.output is None: + assert args.files[0].endswith('.o') + args.output = args.files[0][:-1] + 'mpy' + native_qstr_vals = [] + native_qstr_objs = [] + if args.qstrs is not None: + with open(args.qstrs) as f: + for l in f: + m = re.match(r'#define MP_QSTR_([A-Za-z0-9_]*) \(mp_native_', l) + if m: + native_qstr_vals.append(m.group(1)) + else: + m = re.match(r'#define MP_OBJ_NEW_QSTR_MP_QSTR_([A-Za-z0-9_]*)', l) + if m: + native_qstr_objs.append(m.group(1)) + log(LOG_LEVEL_2, 'qstr vals: ' + ', '.join(native_qstr_vals)) + log(LOG_LEVEL_2, 'qstr objs: ' + ', '.join(native_qstr_objs)) + env = LinkEnv(args.arch) + try: + for file in args.files: + load_object_file(env, file) + link_objects(env, len(native_qstr_vals), len(native_qstr_objs)) + build_mpy(env, env.find_addr('mpy_init'), args.output, native_qstr_vals, native_qstr_objs) + except LinkError as er: + print('LinkError:', er.args[0]) + sys.exit(1) + +def main(): + import argparse + cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.') + cmd_parser.add_argument('--verbose', '-v', action='count', default=1, help='increase verbosity') + cmd_parser.add_argument('--arch', default='x64', help='architecture') + cmd_parser.add_argument('--preprocess', action='store_true', help='preprocess source files') + cmd_parser.add_argument('--qstrs', default=None, help='file defining additional qstrs') + cmd_parser.add_argument('--output', '-o', default=None, help='output .mpy file (default to input with .o->.mpy)') + cmd_parser.add_argument('files', nargs='+', help='input files') + args = cmd_parser.parse_args() + + global log_level + log_level = args.verbose + + if args.preprocess: + do_preprocess(args) + else: + do_link(args) + +if __name__ == '__main__': + main() From e5acd06ad5b7cc144fb26d29baaa041ced065d45 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Nov 2019 11:37:36 +1100 Subject: [PATCH 0765/1299] extmod/modbtree: Use mp_printf instead of printf. --- extmod/modbtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 2a08a9cab04bd..88129e2102366 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -60,7 +60,7 @@ STATIC const mp_obj_type_t btree_type; } void __dbpanic(DB *db) { - printf("__dbpanic(%p)\n", db); + mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db); } STATIC mp_obj_btree_t *btree_new(DB *db) { From bbeaafd9aa0378a4478b0e82d355bd0eee953c84 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Nov 2019 11:38:01 +1100 Subject: [PATCH 0766/1299] extmod: Add dynamic-runtime guards to btree/framebuf/uheapq/ure/uzlib. So they can be built as dynamic native modules, as well as existing static native modules. --- extmod/modbtree.c | 6 ++++++ extmod/modframebuf.c | 4 ++++ extmod/moduheapq.c | 2 ++ extmod/modure.c | 6 ++++++ extmod/moduzlib.c | 6 ++++++ 5 files changed, 24 insertions(+) diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 88129e2102366..a1d576fda970e 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -52,7 +52,9 @@ typedef struct _mp_obj_btree_t { byte next_flags; } mp_obj_btree_t; +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_obj_type_t btree_type; +#endif #define CHECK_ERROR(res) \ if (res == RET_ERROR) { \ @@ -295,6 +297,7 @@ STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs } } +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&btree_close_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&btree_flush_obj) }, @@ -319,6 +322,7 @@ STATIC const mp_obj_type_t btree_type = { .subscr = btree_subscr, .locals_dict = (void*)&btree_locals_dict, }; +#endif STATIC const FILEVTABLE btree_stream_fvtable = { mp_stream_posix_read, @@ -327,6 +331,7 @@ STATIC const FILEVTABLE btree_stream_fvtable = { mp_stream_posix_fsync }; +#if !MICROPY_ENABLE_DYNRUNTIME STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, @@ -373,5 +378,6 @@ const mp_obj_module_t mp_module_btree = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_btree_globals, }; +#endif #endif // MICROPY_PY_BTREE diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index a7f6ba905fbfe..416431cd61bc7 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -580,6 +580,7 @@ STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_text_obj, 4, 5, framebuf_text); +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) }, { MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) }, @@ -601,6 +602,7 @@ STATIC const mp_obj_type_t mp_type_framebuf = { .buffer_p = { .get_buffer = framebuf_get_buffer }, .locals_dict = (mp_obj_dict_t*)&framebuf_locals_dict, }; +#endif // this factory function is provided for backwards compatibility with old FrameBuffer1 class STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) { @@ -624,6 +626,7 @@ STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1); +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) }, { MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) }, @@ -644,5 +647,6 @@ const mp_obj_module_t mp_module_framebuf = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&framebuf_module_globals, }; +#endif #endif // MICROPY_PY_FRAMEBUF diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c index f633052105357..2e8010143d718 100644 --- a/extmod/moduheapq.c +++ b/extmod/moduheapq.c @@ -103,6 +103,7 @@ STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heapify_obj, mod_uheapq_heapify); +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_uheapq_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uheapq) }, { MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_uheapq_heappush_obj) }, @@ -116,5 +117,6 @@ const mp_obj_module_t mp_module_uheapq = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_uheapq_globals, }; +#endif #endif //MICROPY_PY_UHEAPQ diff --git a/extmod/modure.c b/extmod/modure.c index 8a60207053054..f3a9d88f7db10 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -144,6 +144,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_end_obj, 1, 2, match_end); #endif +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t match_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_group), MP_ROM_PTR(&match_group_obj) }, #if MICROPY_PY_URE_MATCH_GROUPS @@ -164,6 +165,7 @@ STATIC const mp_obj_type_t match_type = { .print = match_print, .locals_dict = (void*)&match_locals_dict, }; +#endif STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; @@ -363,6 +365,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub); #endif +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t re_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) }, { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) }, @@ -380,6 +383,7 @@ STATIC const mp_obj_type_t re_type = { .print = re_print, .locals_dict = (void*)&re_locals_dict, }; +#endif STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { (void)n_args; @@ -437,6 +441,7 @@ STATIC mp_obj_t mod_re_sub(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_sub_obj, 3, 5, mod_re_sub); #endif +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ure) }, { MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) }, @@ -456,6 +461,7 @@ const mp_obj_module_t mp_module_ure = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_re_globals, }; +#endif // Source files #include'd here to make sure they're compiled in // only if module is enabled by config setting. diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index f8452c72b9af8..64327f1f7cd93 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -122,6 +122,7 @@ STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er return o->decomp.dest - (byte*)buf; } +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, @@ -129,11 +130,13 @@ STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); +#endif STATIC const mp_stream_p_t decompio_stream_p = { .read = decompio_read, }; +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_obj_type_t decompio_type = { { &mp_type_type }, .name = MP_QSTR_DecompIO, @@ -141,6 +144,7 @@ STATIC const mp_obj_type_t decompio_type = { .protocol = &decompio_stream_p, .locals_dict = (void*)&decompio_locals_dict, }; +#endif STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { mp_obj_t data = args[0]; @@ -201,6 +205,7 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress); +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) }, { MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) }, @@ -213,6 +218,7 @@ const mp_obj_module_t mp_module_uzlib = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_uzlib_globals, }; +#endif // Source files #include'd here to make sure they're compiled in // only if module is enabled by config setting. From 37817ab4ba5fa84624dc9715e01d6bd5a8d187b0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Nov 2019 11:40:54 +1100 Subject: [PATCH 0767/1299] examples/natmod: Add btree example. --- examples/natmod/btree/Makefile | 37 ++++++++ examples/natmod/btree/btree_c.c | 148 ++++++++++++++++++++++++++++++ examples/natmod/btree/btree_py.py | 3 + 3 files changed, 188 insertions(+) create mode 100644 examples/natmod/btree/Makefile create mode 100644 examples/natmod/btree/btree_c.c create mode 100644 examples/natmod/btree/btree_py.py diff --git a/examples/natmod/btree/Makefile b/examples/natmod/btree/Makefile new file mode 100644 index 0000000000000..d795102b4aad8 --- /dev/null +++ b/examples/natmod/btree/Makefile @@ -0,0 +1,37 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in btree so it can coexist) +MOD = btree_$(ARCH) + +# Source files (.c or .py) +SRC = btree_c.c btree_py.py + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx +BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error="(void)" -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) +CFLAGS += -I$(BTREE_DIR)/PORT/include +CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) + +SRC += $(addprefix $(realpath $(BTREE_DIR))/,\ + btree/bt_close.c \ + btree/bt_conv.c \ + btree/bt_delete.c \ + btree/bt_get.c \ + btree/bt_open.c \ + btree/bt_overflow.c \ + btree/bt_page.c \ + btree/bt_put.c \ + btree/bt_search.c \ + btree/bt_seq.c \ + btree/bt_split.c \ + btree/bt_utils.c \ + mpool/mpool.c \ + ) + +include $(MPY_DIR)/py/dynruntime.mk + +# btree needs gnu99 defined +CFLAGS += -std=gnu99 diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c new file mode 100644 index 0000000000000..c8c5cef471173 --- /dev/null +++ b/examples/natmod/btree/btree_c.c @@ -0,0 +1,148 @@ +#define MICROPY_ENABLE_DYNRUNTIME (1) +#define MICROPY_PY_BTREE (1) + +#include "py/dynruntime.h" + +#include + +#if !defined(__linux__) +void *memcpy(void *dst, const void *src, size_t n) { + return mp_fun_table.memmove_(dst, src, n); +} +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +void *memmove(void *dest, const void *src, size_t n) { + return mp_fun_table.memmove_(dest, src, n); +} + +void *malloc(size_t n) { + void *ptr = m_malloc(n); + return ptr; +} +void *realloc(void *ptr, size_t n) { + mp_printf(&mp_plat_print, "UNDEF %d\n", __LINE__); + return NULL; +} +void *calloc(size_t n, size_t m) { + void *ptr = m_malloc(n * m); + // memory already cleared by conservative GC + return ptr; +} + +void free(void *ptr) { + m_free(ptr); +} + +void abort_(void) { + nlr_raise(mp_obj_new_exception(mp_load_global(MP_QSTR_RuntimeError))); +} + +int native_errno; +#if defined(__linux__) +int *__errno_location (void) +#else +int *__errno (void) +#endif +{ + return &native_errno; +} + +ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { + mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { + mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { + const mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + struct mp_stream_seek_t seek_s; + seek_s.offset = offset; + seek_s.whence = whence; + mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &native_errno); + if (res == MP_STREAM_ERROR) { + return -1; + } + return seek_s.offset; +} + +int mp_stream_posix_fsync(void *stream) { + mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno); + if (res == MP_STREAM_ERROR) { + return -1; + } + return res; +} + +mp_obj_type_t btree_type; + +#include "extmod/modbtree.c" + +mp_map_elem_t btree_locals_dict_table[8]; +STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table); + +STATIC mp_obj_t btree_open(size_t n_args, const mp_obj_t *args) { + // Make sure we got a stream object + mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); + + BTREEINFO openinfo = {0}; + openinfo.flags = mp_obj_get_int(args[1]); + openinfo.cachesize = mp_obj_get_int(args[2]); + openinfo.psize = mp_obj_get_int(args[3]); + openinfo.minkeypage = mp_obj_get_int(args[4]); + DB *db = __bt_open(MP_OBJ_TO_PTR(args[0]), &btree_stream_fvtable, &openinfo, 0); + if (db == NULL) { + mp_raise_OSError(native_errno); + } + + return MP_OBJ_FROM_PTR(btree_new(db)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + btree_type.base.type = (void*)&mp_fun_table.type_type; + btree_type.name = MP_QSTR_btree; + btree_type.print = btree_print; + btree_type.getiter = btree_getiter; + btree_type.iternext = btree_iternext; + btree_type.binary_op = btree_binary_op; + btree_type.subscr = btree_subscr; + btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) }; + btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) }; + btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) }; + btree_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_put), MP_OBJ_FROM_PTR(&btree_put_obj) }; + btree_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_seq), MP_OBJ_FROM_PTR(&btree_seq_obj) }; + btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) }; + btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) }; + btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) }; + btree_type.locals_dict = (void*)&btree_locals_dict; + + mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj)); + mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL)); + mp_store_global(MP_QSTR_DESC, MP_OBJ_NEW_SMALL_INT(FLAG_DESC)); + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/btree/btree_py.py b/examples/natmod/btree/btree_py.py new file mode 100644 index 0000000000000..bd53c084a13be --- /dev/null +++ b/examples/natmod/btree/btree_py.py @@ -0,0 +1,3 @@ +# Implemented in Python to support keyword arguments +def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0): + return _open(stream, flags, cachesize, pagesize, minkeypage) From 83f9fb169e5d9b9304e06237a747a30d3ea53458 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Nov 2019 11:41:39 +1100 Subject: [PATCH 0768/1299] examples/natmod: Add uheapq example. --- examples/natmod/uheapq/Makefile | 13 +++++++++++++ examples/natmod/uheapq/uheapq.c | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 examples/natmod/uheapq/Makefile create mode 100644 examples/natmod/uheapq/uheapq.c diff --git a/examples/natmod/uheapq/Makefile b/examples/natmod/uheapq/Makefile new file mode 100644 index 0000000000000..55de3cc081857 --- /dev/null +++ b/examples/natmod/uheapq/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in uheapq so it can coexist) +MOD = uheapq_$(ARCH) + +# Source files (.c or .py) +SRC = uheapq.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/uheapq/uheapq.c b/examples/natmod/uheapq/uheapq.c new file mode 100644 index 0000000000000..df880bd382755 --- /dev/null +++ b/examples/natmod/uheapq/uheapq.c @@ -0,0 +1,17 @@ +#define MICROPY_ENABLE_DYNRUNTIME (1) +#define MICROPY_PY_UHEAPQ (1) + +#include "py/dynruntime.h" + +#include "extmod/moduheapq.c" + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq)); + mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj)); + mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj)); + mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj)); + + MP_DYNRUNTIME_INIT_EXIT +} From 16e591e412ec4be511180910f6f293fee01ad615 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 5 Nov 2019 11:42:59 +1100 Subject: [PATCH 0769/1299] examples/natmod: Add uzlib example. --- examples/natmod/uzlib/Makefile | 13 ++++++++++++ examples/natmod/uzlib/uzlib.c | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 examples/natmod/uzlib/Makefile create mode 100644 examples/natmod/uzlib/uzlib.c diff --git a/examples/natmod/uzlib/Makefile b/examples/natmod/uzlib/Makefile new file mode 100644 index 0000000000000..8761caf2dd26c --- /dev/null +++ b/examples/natmod/uzlib/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in uzlib so it can coexist) +MOD = uzlib_$(ARCH) + +# Source files (.c or .py) +SRC = uzlib.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c new file mode 100644 index 0000000000000..4873171e5eea9 --- /dev/null +++ b/examples/natmod/uzlib/uzlib.c @@ -0,0 +1,36 @@ +#define MICROPY_ENABLE_DYNRUNTIME (1) +#define MICROPY_PY_UZLIB (1) + +#include "py/dynruntime.h" + +#if !defined(__linux__) +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +mp_obj_type_t decompio_type; + +#include "extmod/moduzlib.c" + +mp_map_elem_t decompio_locals_dict_table[3]; +STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + decompio_type.base.type = mp_fun_table.type_type; + decompio_type.name = MP_QSTR_DecompIO; + decompio_type.make_new = decompio_make_new; + decompio_type.protocol = &decompio_stream_p; + decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) }; + decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) }; + decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) }; + decompio_type.locals_dict = (void*)&decompio_locals_dict; + + mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib)); + mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj)); + mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type)); + + MP_DYNRUNTIME_INIT_EXIT +} From 2a485e1084d8706aae4533900c26307f346c6ca5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Dec 2019 15:01:36 +1100 Subject: [PATCH 0770/1299] examples/natmod: Add framebuf example. --- examples/natmod/framebuf/Makefile | 13 ++++++++ examples/natmod/framebuf/framebuf.c | 50 +++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 examples/natmod/framebuf/Makefile create mode 100644 examples/natmod/framebuf/framebuf.c diff --git a/examples/natmod/framebuf/Makefile b/examples/natmod/framebuf/Makefile new file mode 100644 index 0000000000000..2e2b815975432 --- /dev/null +++ b/examples/natmod/framebuf/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in framebuf so it can coexist) +MOD = framebuf_$(ARCH) + +# Source files (.c or .py) +SRC = framebuf.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c new file mode 100644 index 0000000000000..8f322c204af1d --- /dev/null +++ b/examples/natmod/framebuf/framebuf.c @@ -0,0 +1,50 @@ +#define MICROPY_ENABLE_DYNRUNTIME (1) +#define MICROPY_PY_FRAMEBUF (1) + +#include "py/dynruntime.h" + +#if !defined(__linux__) +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +mp_obj_type_t mp_type_framebuf; + +#include "extmod/modframebuf.c" + +mp_map_elem_t framebuf_locals_dict_table[10]; +STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + mp_type_framebuf.base.type = (void*)&mp_type_type; + mp_type_framebuf.name = MP_QSTR_FrameBuffer; + mp_type_framebuf.make_new = framebuf_make_new; + mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer; + framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) }; + framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) }; + framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) }; + framebuf_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_hline), MP_OBJ_FROM_PTR(&framebuf_hline_obj) }; + framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) }; + framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) }; + framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) }; + framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) }; + framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) }; + framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) }; + mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict; + + mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf)); + mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj)); + mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB)); + mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB)); + mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565)); + mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB)); + mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB)); + mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8)); + mp_store_global(MP_QSTR_MONO_HLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB)); + mp_store_global(MP_QSTR_MONO_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB)); + + MP_DYNRUNTIME_INIT_EXIT +} From 42c1aed2bba55b759e54139421044a05ccd4bfc6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Dec 2019 15:02:04 +1100 Subject: [PATCH 0771/1299] examples/natmod: Add ure example. --- examples/natmod/ure/Makefile | 13 ++++++ examples/natmod/ure/ure.c | 79 ++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 examples/natmod/ure/Makefile create mode 100644 examples/natmod/ure/ure.c diff --git a/examples/natmod/ure/Makefile b/examples/natmod/ure/Makefile new file mode 100644 index 0000000000000..f5254298fdd90 --- /dev/null +++ b/examples/natmod/ure/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in ure so it can coexist) +MOD = ure_$(ARCH) + +# Source files (.c or .py) +SRC = ure.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c new file mode 100644 index 0000000000000..6c9e9e307ede7 --- /dev/null +++ b/examples/natmod/ure/ure.c @@ -0,0 +1,79 @@ +#define MICROPY_ENABLE_DYNRUNTIME (1) +#define MICROPY_STACK_CHECK (1) +#define MICROPY_PY_URE (1) +#define MICROPY_PY_URE_MATCH_GROUPS (1) +#define MICROPY_PY_URE_MATCH_SPAN_START_END (1) +#define MICROPY_PY_URE_SUB (0) // requires vstr interface + +#include +#include "py/dynruntime.h" + +#define STACK_LIMIT (2048) + +const char *stack_top; + +void mp_stack_check(void) { + // Assumes descending stack on target + volatile char dummy; + if (stack_top - &dummy >= STACK_LIMIT) { + mp_raise_msg(&mp_type_RuntimeError, "maximum recursion depth exceeded"); + } +} + +#if !defined(__linux__) +void *memcpy(void *dst, const void *src, size_t n) { + return mp_fun_table.memmove_(dst, src, n); +} +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +void *memmove(void *dest, const void *src, size_t n) { + return mp_fun_table.memmove_(dest, src, n); +} + +mp_obj_type_t match_type; +mp_obj_type_t re_type; + +#include "extmod/modure.c" + +mp_map_elem_t match_locals_dict_table[5]; +STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); + +mp_map_elem_t re_locals_dict_table[3]; +STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + char dummy; + stack_top = &dummy; + + // Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section + // to copy in this key/value pair if they are specified as a struct, so assign them separately. + + match_type.base.type = (void*)&mp_fun_table.type_type; + match_type.name = MP_QSTR_match; + match_type.print = match_print; + match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) }; + match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) }; + match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) }; + match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) }; + match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) }; + match_type.locals_dict = (void*)&match_locals_dict; + + re_type.base.type = (void*)&mp_fun_table.type_type; + re_type.name = MP_QSTR_ure; + re_type.print = re_print; + re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) }; + re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) }; + re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) }; + re_type.locals_dict = (void*)&re_locals_dict; + + mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj)); + mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&mod_re_match_obj)); + mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&mod_re_search_obj)); + + MP_DYNRUNTIME_INIT_EXIT +} From 9ac949cdbd78d15f5edeaa651859659e8b382181 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 30 Nov 2019 23:00:56 +1100 Subject: [PATCH 0772/1299] py/persistentcode: Make ARM Thumb archs support multiple sub-archs. --- py/persistentcode.c | 8 +++++--- py/persistentcode.h | 29 ++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index 1e3b5368b43ae..8bf46202ba63a 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -526,9 +526,11 @@ mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) { || read_uint(reader, NULL) > QSTR_WINDOW_SIZE) { mp_raise_ValueError("incompatible .mpy file"); } - if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE - && MPY_FEATURE_DECODE_ARCH(header[2]) != MPY_FEATURE_ARCH) { - mp_raise_ValueError("incompatible .mpy arch"); + if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) { + byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); + if (!MPY_FEATURE_ARCH_TEST(arch)) { + mp_raise_ValueError("incompatible .mpy arch"); + } } qstr_window_t qw; qw.idx = 0; diff --git a/py/persistentcode.h b/py/persistentcode.h index fde7a4625dceb..8769ef584d2d7 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -55,19 +55,34 @@ // Define the host architecture #if MICROPY_EMIT_X86 -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X86) + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X86) #elif MICROPY_EMIT_X64 -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X64) + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_X64) #elif MICROPY_EMIT_THUMB -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7M) + #if defined(__thumb2__) + #if defined(__ARM_FP) && (__ARM_FP & 8) == 8 + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7EMDP) + #elif defined(__ARM_FP) && (__ARM_FP & 4) == 4 + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7EMSP) + #else + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7EM) + #endif + #else + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV7M) + #endif + #define MPY_FEATURE_ARCH_TEST(x) (MP_NATIVE_ARCH_ARMV6M <= (x) && (x) <= MPY_FEATURE_ARCH) #elif MICROPY_EMIT_ARM -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV6) + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_ARMV6) #elif MICROPY_EMIT_XTENSA -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSA) + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSA) #elif MICROPY_EMIT_XTENSAWIN -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSAWIN) + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSAWIN) #else -#define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) +#endif + +#ifndef MPY_FEATURE_ARCH_TEST +#define MPY_FEATURE_ARCH_TEST(x) ((x) == MPY_FEATURE_ARCH) #endif // 16-bit little-endian integer with the second and third bytes of supported .mpy files From ff58961944f4f2380e9610a4d18c53c08f68060e Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 30 Nov 2019 23:02:50 +1100 Subject: [PATCH 0773/1299] py/nativeglue: Add float new/get functions with both single and double. --- py/nativeglue.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ py/nativeglue.h | 4 ++++ 2 files changed, 50 insertions(+) diff --git a/py/nativeglue.c b/py/nativeglue.c index a88d8c1b9ba30..1a7f92f94517f 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -211,6 +211,48 @@ STATIC bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *re return false; } +#if MICROPY_PY_BUILTINS_FLOAT + +STATIC mp_obj_t mp_obj_new_float_from_f(float f) { + return mp_obj_new_float((mp_float_t)f); +} + +STATIC mp_obj_t mp_obj_new_float_from_d(double d) { + return mp_obj_new_float((mp_float_t)d); +} + +STATIC float mp_obj_get_float_to_f(mp_obj_t o) { + return (float)mp_obj_get_float(o); +} + +STATIC double mp_obj_get_float_to_d(mp_obj_t o) { + return (double)mp_obj_get_float(o); +} + +#else + +STATIC mp_obj_t mp_obj_new_float_from_f(float f) { + (void)f; + mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); +} + +STATIC mp_obj_t mp_obj_new_float_from_d(double d) { + (void)d; + mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); +} + +STATIC float mp_obj_get_float_to_f(mp_obj_t o) { + (void)o; + mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); +} + +STATIC double mp_obj_get_float_to_d(mp_obj_t o) { + (void)o; + mp_raise_msg(&mp_type_RuntimeError, "float unsupported"); +} + +#endif + // these must correspond to the respective enum in runtime0.h const mp_fun_table_t mp_fun_table = { &mp_const_none_obj, @@ -282,6 +324,10 @@ const mp_fun_table_t mp_fun_table = { mp_obj_new_str, mp_obj_new_bytes, mp_obj_new_bytearray_by_ref, + mp_obj_new_float_from_f, + mp_obj_new_float_from_d, + mp_obj_get_float_to_f, + mp_obj_get_float_to_d, mp_get_buffer_raise, mp_get_stream_raise, &mp_plat_print, diff --git a/py/nativeglue.h b/py/nativeglue.h index 9abae89df2127..021e7a8ecb7ea 100644 --- a/py/nativeglue.h +++ b/py/nativeglue.h @@ -150,6 +150,10 @@ typedef struct _mp_fun_table_t { mp_obj_t (*obj_new_str)(const char* data, size_t len); mp_obj_t (*obj_new_bytes)(const byte* data, size_t len); mp_obj_t (*obj_new_bytearray_by_ref)(size_t n, void *items); + mp_obj_t (*obj_new_float_from_f)(float f); + mp_obj_t (*obj_new_float_from_d)(double d); + float (*obj_get_float_to_f)(mp_obj_t o); + double (*obj_get_float_to_d)(mp_obj_t o); void (*get_buffer_raise)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); const mp_stream_p_t *(*get_stream_raise)(mp_obj_t self_in, int flags); const mp_print_t *plat_print; From abc642973db46fbce7494d34ea0ef2539b339be0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 30 Nov 2019 23:03:09 +1100 Subject: [PATCH 0774/1299] py/dynruntime: Add support for float API to make/get floats. We don't want to add a feature flag to .mpy files that indicate float support because it will get complex and difficult to use. Instead the .mpy is built using whatever precision it chooses (float or double) and the native glue API will convert between this choice and what the host runtime actually uses. --- py/dynruntime.h | 16 ++++++++++++++++ py/dynruntime.mk | 10 ++++++++++ tools/mpy_ld.py | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/py/dynruntime.h b/py/dynruntime.h index 34cf6010c46fd..a83aa905c114e 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -190,4 +190,20 @@ static inline void mp_raise_OSError_dyn(int er) { nlr_raise(mp_call_function_n_kw(mp_load_global(MP_QSTR_OSError), 1, 0, &args[0])); } +/******************************************************************************/ +// Floating point + +#define mp_obj_new_float_from_f(f) (mp_fun_table.obj_new_float_from_f((f))) +#define mp_obj_new_float_from_d(d) (mp_fun_table.obj_new_float_from_d((d))) +#define mp_obj_get_float_to_f(o) (mp_fun_table.obj_get_float_to_f((o))) +#define mp_obj_get_float_to_d(o) (mp_fun_table.obj_get_float_to_d((o))) + +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define mp_obj_new_float(f) (mp_obj_new_float_from_f((f))) +#define mp_obj_get_float(o) (mp_obj_get_float_to_f((o))) +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define mp_obj_new_float(f) (mp_obj_new_float_from_d((f))) +#define mp_obj_get_float(o) (mp_obj_get_float_to_d((o))) +#endif + #endif // MICROPY_INCLUDED_PY_DYNRUNTIME_H diff --git a/py/dynruntime.mk b/py/dynruntime.mk index b01b80e0dd8c2..8b65745afdf78 100644 --- a/py/dynruntime.mk +++ b/py/dynruntime.mk @@ -46,6 +46,7 @@ ifeq ($(ARCH),x86) CROSS = CFLAGS += -m32 -fno-stack-protector MPY_CROSS_FLAGS += -mcache-lookup-bc +MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),x64) @@ -53,12 +54,14 @@ else ifeq ($(ARCH),x64) CROSS = CFLAGS += -fno-stack-protector MPY_CROSS_FLAGS += -mcache-lookup-bc +MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),armv7m) # thumb CROSS = arm-none-eabi- CFLAGS += -mthumb -mcpu=cortex-m3 +MICROPY_FLOAT_IMPL ?= none else ifeq ($(ARCH),armv7emsp) @@ -66,6 +69,7 @@ else ifeq ($(ARCH),armv7emsp) CROSS = arm-none-eabi- CFLAGS += -mthumb -mcpu=cortex-m4 CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard +MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),armv7emdp) @@ -73,23 +77,29 @@ else ifeq ($(ARCH),armv7emdp) CROSS = arm-none-eabi- CFLAGS += -mthumb -mcpu=cortex-m7 CFLAGS += -mfpu=fpv5-d16 -mfloat-abi=hard +MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),xtensa) # xtensa CROSS = xtensa-lx106-elf- CFLAGS += -mforce-l32 +MICROPY_FLOAT_IMPL ?= none else ifeq ($(ARCH),xtensawin) # xtensawin CROSS = xtensa-esp32-elf- CFLAGS += +MICROPY_FLOAT_IMPL ?= float else $(error architecture '$(ARCH)' not supported) endif +MICROPY_FLOAT_IMPL_UPPER = $(shell echo $(MICROPY_FLOAT_IMPL) | tr '[:lower:]' '[:upper:]') +CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_$(MICROPY_FLOAT_IMPL_UPPER) + CFLAGS += $(CFLAGS_EXTRA) ################################################################################ diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index 07105caac9694..ec600f9671d23 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -663,7 +663,7 @@ def link_objects(env, native_qstr_vals_len, native_qstr_objs_len): # Resolve unknown symbols mp_fun_table_sec = Section('.external.mp_fun_table', b'', 0) - fun_table = {key: 63 + idx + fun_table = {key: 67 + idx for idx, key in enumerate([ 'mp_type_type', 'mp_type_str', From 111d1ffb6473950274bb506e1a27c01b33ea3d61 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 2 Dec 2019 16:27:24 +1100 Subject: [PATCH 0775/1299] tests/import: Add test for importing viper code with additional flags. --- tests/import/mpy_native.py | 21 +++++++++++++++++++++ tests/import/mpy_native.py.exp | 1 + 2 files changed, 22 insertions(+) diff --git a/tests/import/mpy_native.py b/tests/import/mpy_native.py index c33b3350c38d1..4ee537f4afb08 100644 --- a/tests/import/mpy_native.py +++ b/tests/import/mpy_native.py @@ -73,6 +73,27 @@ def open(self, path, mode): b'\x00\x00\x00\x00\x00\x00\x00\x00' # dummy machine code b'\x00\x00\x00' # scope_flags, n_pos_args, type_sig ), + + # test loading viper with additional scope flags and relocation + '/mod2.mpy': ( + b'M\x05\x0b\x1f\x20' # header + + b'\x20' # n bytes, bytecode + b'\x00\x08\x02m\x02m' # prelude + b'\x51' # LOAD_CONST_NONE + b'\x63' # RETURN_VALUE + + b'\x00\x01' # n_obj, n_raw_code + + b'\x12' # n bytes(=4), viper code + b'\x00\x00\x00\x00' # dummy machine code + b'\x00' # n_qstr + b'\x70' # scope_flags: VIPERBSS | VIPERRODATA | VIPERRELOC + b'\x00\x00' # n_obj, n_raw_code + b'\x06rodata' # rodata, 6 bytes + b'\x04' # bss, 4 bytes + b'\x03\x01\x00' # dummy relocation of rodata + ), } # create and mount a user filesystem diff --git a/tests/import/mpy_native.py.exp b/tests/import/mpy_native.py.exp index b73812094a493..320cac09d8c85 100644 --- a/tests/import/mpy_native.py.exp +++ b/tests/import/mpy_native.py.exp @@ -1,2 +1,3 @@ mod0 ValueError incompatible .mpy arch mod1 OK +mod2 OK From fc97d6d1b5f4c249e755e9190518aad8020980ba Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 10 Dec 2019 14:57:12 +1100 Subject: [PATCH 0776/1299] tools/mpy-tool.py: Raise exception if trying to freeze relocatable mpy. --- tools/mpy-tool.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 8bc37734c7034..77a129944bfc8 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -474,6 +474,9 @@ def _link_qstr(self, pc, kind, qst): assert 0 def freeze(self, parent_name): + if self.prelude[2] & ~0x0f: + raise FreezeError('unable to freeze code with relocations') + self.freeze_children(parent_name) # generate native code data From 4eef940edbd3ee4eecead37785cafd9845d763a2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 11 Dec 2019 14:39:27 +1100 Subject: [PATCH 0777/1299] tests: Add script to run dynamic-native-module tests. --- tests/run-natmodtests.py | 187 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100755 tests/run-natmodtests.py diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py new file mode 100755 index 0000000000000..186c30b83162e --- /dev/null +++ b/tests/run-natmodtests.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 + +# This file is part of the MicroPython project, http://micropython.org/ +# The MIT License (MIT) +# Copyright (c) 2019 Damien P. George + +import os +import subprocess +import sys +import argparse + +sys.path.append('../tools') +import pyboard + +# Paths for host executables +CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') +MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython_coverage') + +NATMOD_EXAMPLE_DIR = '../examples/natmod/' + +# Supported tests and their corresponding mpy module +TEST_MAPPINGS = { + 'btree': 'btree/btree_$(ARCH).mpy', + 'framebuf': 'framebuf/framebuf_$(ARCH).mpy', + 'uheapq': 'uheapq/uheapq_$(ARCH).mpy', + 'ure': 'ure/ure_$(ARCH).mpy', + 'uzlib': 'uzlib/uzlib_$(ARCH).mpy', +} + +# Code to allow a target MicroPython to import an .mpy from RAM +injected_import_hook_code = """\ +import sys, uos, uio +class __File(uio.IOBase): + def __init__(self): + self.off = 0 + def ioctl(self, request, arg): + return 0 + def readinto(self, buf): + buf[:] = memoryview(__buf)[self.off:self.off + len(buf)] + self.off += len(buf) + return len(buf) +class __FS: + def mount(self, readonly, mkfs): + pass + def chdir(self, path): + pass + def stat(self, path): + if path == '__injected.mpy': + return tuple(0 for _ in range(10)) + else: + raise OSError(-2) # ENOENT + def open(self, path, mode): + return __File() +uos.mount(__FS(), '/__remote') +uos.chdir('/__remote') +sys.modules['{}'] = __import__('__injected') +""" + +class TargetSubprocess: + def __init__(self, cmd): + self.cmd = cmd + + def close(self): + pass + + def run_script(self, script): + try: + p = subprocess.run(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, input=script) + return p.stdout, None + except subprocess.CalledProcessError as er: + return b'', er + +class TargetPyboard: + def __init__(self, pyb): + self.pyb = pyb + self.pyb.enter_raw_repl() + + def close(self): + self.pyb.exit_raw_repl() + self.pyb.close() + + def run_script(self, script): + try: + self.pyb.enter_raw_repl() + output = self.pyb.exec_(script) + output = output.replace(b'\r\n', b'\n') + return output, None + except pyboard.PyboardError as er: + return b'', er + +def run_tests(target_truth, target, args, stats): + for test_file in args.files: + # Find supported test + for k, v in TEST_MAPPINGS.items(): + if test_file.find(k) != -1: + test_module = k + test_mpy = v.replace('$(ARCH)', args.arch) + break + else: + print('---- {} - no matching mpy'.format(test_file)) + continue + + # Read test script + with open(test_file, 'rb') as f: + test_file_data = f.read() + + # Create full test with embedded .mpy + try: + with open(NATMOD_EXAMPLE_DIR + test_mpy, 'rb') as f: + test_script = b'__buf=' + bytes(repr(f.read()), 'ascii') + b'\n' + except OSError: + print('---- {} - mpy file not compiled'.format(test_file)) + continue + test_script += bytes(injected_import_hook_code.format(test_module), 'ascii') + test_script += test_file_data + + # Run test under MicroPython + result_out, error = target.run_script(test_script) + + # Work out result of test + extra = '' + if error is None and result_out == b'SKIP\n': + result = 'SKIP' + elif error is not None: + result = 'FAIL' + extra = ' - ' + str(error) + else: + # Check result against truth + try: + with open(test_file + '.exp', 'rb') as f: + result_exp = f.read() + error = None + except OSError: + result_exp, error = target_truth.run_script(test_file_data) + if error is not None: + result = 'TRUTH FAIL' + elif result_out != result_exp: + result = 'FAIL' + print(result_out) + else: + result = 'pass' + + # Accumulate statistics + stats['total'] += 1 + if result == 'pass': + stats['pass'] += 1 + elif result == 'SKIP': + stats['skip'] += 1 + else: + stats['fail'] += 1 + + # Print result + print('{:4} {}{}'.format(result, test_file, extra)) + +def main(): + cmd_parser = argparse.ArgumentParser(description='Run dynamic-native-module tests under MicroPython') + cmd_parser.add_argument('-p', '--pyboard', action='store_true', help='run tests via pyboard.py') + cmd_parser.add_argument('-d', '--device', default='/dev/ttyACM0', help='the device for pyboard.py') + cmd_parser.add_argument('-a', '--arch', default='x64', help='native architecture of the target') + cmd_parser.add_argument('files', nargs='*', help='input test files') + args = cmd_parser.parse_args() + + target_truth = TargetSubprocess([CPYTHON3]) + + if args.pyboard: + target = TargetPyboard(pyboard.Pyboard(args.device)) + else: + target = TargetSubprocess([MICROPYTHON]) + + stats = {'total': 0, 'pass': 0, 'fail':0, 'skip': 0} + run_tests(target_truth, target, args, stats) + + target.close() + target_truth.close() + + print('{} tests performed'.format(stats['total'])) + print('{} tests passed'.format(stats['pass'])) + if stats['fail']: + print('{} tests failed'.format(stats['fail'])) + if stats['skip']: + print('{} tests skipped'.format(stats['skip'])) + + if stats['fail']: + sys.exit(1) + +if __name__ == "__main__": + main() From 60c3c22a0dcd5aba9e65ae4c3890889f42a18567 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Dec 2019 15:02:27 +1100 Subject: [PATCH 0778/1299] examples/natmod: Add features1 and features2 examples. --- examples/natmod/features1/Makefile | 14 ++++ examples/natmod/features1/features1.c | 106 ++++++++++++++++++++++++++ examples/natmod/features2/Makefile | 14 ++++ examples/natmod/features2/main.c | 83 ++++++++++++++++++++ examples/natmod/features2/prod.c | 9 +++ examples/natmod/features2/prod.h | 1 + examples/natmod/features2/test.py | 26 +++++++ 7 files changed, 253 insertions(+) create mode 100644 examples/natmod/features1/Makefile create mode 100644 examples/natmod/features1/features1.c create mode 100644 examples/natmod/features2/Makefile create mode 100644 examples/natmod/features2/main.c create mode 100644 examples/natmod/features2/prod.c create mode 100644 examples/natmod/features2/prod.h create mode 100644 examples/natmod/features2/test.py diff --git a/examples/natmod/features1/Makefile b/examples/natmod/features1/Makefile new file mode 100644 index 0000000000000..010640daf9746 --- /dev/null +++ b/examples/natmod/features1/Makefile @@ -0,0 +1,14 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module +MOD = features1 + +# Source files (.c or .py) +SRC = features1.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +# Include to get the rules for compiling and linking the module +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features1/features1.c b/examples/natmod/features1/features1.c new file mode 100644 index 0000000000000..1bfbe50b95283 --- /dev/null +++ b/examples/natmod/features1/features1.c @@ -0,0 +1,106 @@ +/* This example demonstrates the following features in a native module: + - defining simple functions exposed to Python + - defining local, helper C functions + - defining constant integers and strings exposed to Python + - getting and creating integer objects + - creating Python lists + - raising exceptions + - allocating memory + - BSS and constant data (rodata) + - relocated pointers in rodata +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// BSS (zero) data +uint16_t data16[4]; + +// Constant data (rodata) +const uint8_t table8[] = { 0, 1, 1, 2, 3, 5, 8, 13 }; +const uint16_t table16[] = { 0x1000, 0x2000 }; + +// Constant data pointing to BSS/constant data +uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3] }; +const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] }; + +// A simple function that adds its 2 arguments (must be integers) +STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) { + mp_int_t x = mp_obj_get_int(x_in); + mp_int_t y = mp_obj_get_int(y_in); + return mp_obj_new_int(x + y); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); + +// A local helper function (not exposed to Python) +STATIC mp_int_t fibonacci_helper(mp_int_t x) { + if (x < MP_ARRAY_SIZE(table8)) { + return table8[x]; + } else { + return fibonacci_helper(x - 1) + fibonacci_helper(x - 2); + } +} + +// A function which computes Fibonacci numbers +STATIC mp_obj_t fibonacci(mp_obj_t x_in) { + mp_int_t x = mp_obj_get_int(x_in); + if (x < 0) { + mp_raise_ValueError("can't compute negative Fibonacci number"); + } + return mp_obj_new_int(fibonacci_helper(x)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci); + +// A function that accesses the BSS data +STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + // Create a list holding all items from data16 + mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL)); + for (int i = 0; i < MP_ARRAY_SIZE(data16); ++i) { + lst->items[i] = mp_obj_new_int(data16[i]); + } + return MP_OBJ_FROM_PTR(lst); + } else if (n_args == 1) { + // Get one item from data16 + mp_int_t idx = mp_obj_get_int(args[0]) & 3; + return mp_obj_new_int(data16[idx]); + } else { + // Set one item in data16 (via table_ptr16a) + mp_int_t idx = mp_obj_get_int(args[0]) & 3; + *table_ptr16a[idx] = mp_obj_get_int(args[1]); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access); + +// A function that allocates memory and creates a bytearray +STATIC mp_obj_t make_array(void) { + uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b)); + for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) { + ptr[i] = *table_ptr16b[i]; + } + return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array); + +// This is the entry point and is called when the module is imported +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Messages can be printed as usualy + mp_printf(&mp_plat_print, "initialising module self=%p\n", self); + + // Make the functions available in the module's namespace + mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); + mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj)); + mp_store_global(MP_QSTR_access, MP_OBJ_FROM_PTR(&access_obj)); + mp_store_global(MP_QSTR_make_array, MP_OBJ_FROM_PTR(&make_array_obj)); + + // Add some constants to the module's namespace + mp_store_global(MP_QSTR_VAL, MP_OBJ_NEW_SMALL_INT(42)); + mp_store_global(MP_QSTR_MSG, MP_OBJ_NEW_QSTR(MP_QSTR_HELLO_MICROPYTHON)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/features2/Makefile b/examples/natmod/features2/Makefile new file mode 100644 index 0000000000000..4fd23c6879d47 --- /dev/null +++ b/examples/natmod/features2/Makefile @@ -0,0 +1,14 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module +MOD = features2 + +# Source files (.c or .py) +SRC = main.c prod.c test.py + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +# Include to get the rules for compiling and linking the module +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features2/main.c b/examples/natmod/features2/main.c new file mode 100644 index 0000000000000..de83bf2bed194 --- /dev/null +++ b/examples/natmod/features2/main.c @@ -0,0 +1,83 @@ +/* This example demonstrates the following features in a native module: + - using floats + - defining additional code in Python (see test.py) + - have extra C code in a separate file (see prod.c) +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// Include the header for auxiliary C code for this module +#include "prod.h" + +// Automatically detect if this module should include double-precision code. +// If double precision is supported by the target architecture then it can +// be used in native module regardless of what float setting the target +// MicroPython runtime uses (being none, float or double). +#if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8)) +#define USE_DOUBLE 1 +#else +#define USE_DOUBLE 0 +#endif + +// A function that uses the default float type configured for the current target +// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level +STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); + +// A function that explicitly uses single precision floats +STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f); + +#if USE_DOUBLE +// A function that explicitly uses double precision floats +STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d); +#endif + +// A function that computes the product of floats in an array. +// This function uses the most general C argument interface, which is more difficult +// to use but has access to the globals dict of the module via self->globals. +STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // Check number of arguments is valid + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + // Extract buffer pointer and verify typecode + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW); + if (bufinfo.typecode != 'f') { + mp_raise_ValueError("expecting float array"); + } + + // Compute product, store result back in first element of array + float *ptr = bufinfo.buf; + float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr); + ptr[0] = prod; + + return mp_const_none; +} + +// This is the entry point and is called when the module is imported +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Make the functions available in the module's namespace + mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); + mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj)); + #if USE_DOUBLE + mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj)); + #endif + + // The productf function uses the most general C argument interface + mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/features2/prod.c b/examples/natmod/features2/prod.c new file mode 100644 index 0000000000000..7791dcad1d214 --- /dev/null +++ b/examples/natmod/features2/prod.c @@ -0,0 +1,9 @@ +#include "prod.h" + +float prod_array(int n, float *ar) { + float ans = 1; + for (int i = 0; i < n; ++i) { + ans *= ar[i]; + } + return ans; +} diff --git a/examples/natmod/features2/prod.h b/examples/natmod/features2/prod.h new file mode 100644 index 0000000000000..f27dd8d0330fe --- /dev/null +++ b/examples/natmod/features2/prod.h @@ -0,0 +1 @@ +float prod_array(int n, float *ar); diff --git a/examples/natmod/features2/test.py b/examples/natmod/features2/test.py new file mode 100644 index 0000000000000..2e9db00f44d40 --- /dev/null +++ b/examples/natmod/features2/test.py @@ -0,0 +1,26 @@ +# This Python code will be merged with the C code in main.c + +import array + +def isclose(a, b): + return abs(a - b) < 1e-3 + +def test(): + tests = [ + isclose(add(0.1, 0.2), 0.3), + isclose(add_f(0.1, 0.2), 0.3), + ] + + ar = array.array('f', [1, 2, 3.5]) + productf(ar) + tests.append(isclose(ar[0], 7)) + + if 'add_d' in globals(): + tests.append(isclose(add_d(0.1, 0.2), 0.3)) + + print(tests) + + if not all(tests): + raise SystemExit(1) + +test() From ac769672fd0b94b237fac6e0bfb411fa92f846cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 12 Dec 2019 17:45:02 +1100 Subject: [PATCH 0779/1299] travis: Add tests for building and importing dynamic native modules. --- .travis.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0f57bc3fe86b1..fef8bbbcfb062 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,7 +62,10 @@ jobs: - stage: test env: NAME="unix coverage build and tests" install: + - sudo apt-get install python3-pip - sudo pip install cpp-coveralls + - sudo pip3 install setuptools + - sudo pip3 install pyelftools - gcc --version - python3 --version script: @@ -78,6 +81,17 @@ jobs: - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --emit native -d basics float micropython) # test when input script comes from stdin - cat tests/basics/0prelim.py | ports/unix/micropython_coverage | grep -q 'abc' + # test building native mpy modules + - make -C examples/natmod/features1 ARCH=x64 + - make -C examples/natmod/features2 ARCH=x64 + - make -C examples/natmod/btree ARCH=x64 + - make -C examples/natmod/framebuf ARCH=x64 + - make -C examples/natmod/uheapq ARCH=x64 + - make -C examples/natmod/ure ARCH=x64 + - make -C examples/natmod/uzlib ARCH=x64 + # test importing .mpy generated by mpy_ld.py + - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython_coverage -m features2 + - (cd tests && ./run-natmodtests.py extmod/{btree*,framebuf*,uheapq*,ure*,uzlib*}.py) # run coveralls coverage analysis (try to, even if some builds/tests failed) - (cd ports/unix && coveralls --root ../.. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) after_failure: From cd9de63c0e8ac242148c87869d37dcc295c7497a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 12:34:42 +1100 Subject: [PATCH 0780/1299] drivers/wiznet5k: Allow selecting maximum fixed buffer size for MACRAW. Enabling WIZCHIP_USE_MAX_BUFFER will make the TX/RX buffers the maximum available size, for use with MACRAW mode. --- drivers/wiznet5k/ethernet/w5200/w5200.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.c b/drivers/wiznet5k/ethernet/w5200/w5200.c index 8c3780792eff7..a84d3c9fa7bcb 100644 --- a/drivers/wiznet5k/ethernet/w5200/w5200.c +++ b/drivers/wiznet5k/ethernet/w5200/w5200.c @@ -52,10 +52,19 @@ #include "w5200.h" +#if WIZCHIP_USE_MAX_BUFFER +// This option is intended to be used when MACRAW mode is enabled, to allow +// the single raw socket to use all the available buffer space. +#define SMASK (16 * 1024 - 1) /* tx buffer mask */ +#define RMASK (16 * 1024 - 1) /* rx buffer mask */ +#define SSIZE (16 * 1024) /* max tx buffer size */ +#define RSIZE (16 * 1024) /* max rx buffer size */ +#else #define SMASK (0x7ff) /* tx buffer mask */ #define RMASK (0x7ff) /* rx buffer mask */ #define SSIZE (2048) /* max tx buffer size */ #define RSIZE (2048) /* max rx buffer size */ +#endif #define TXBUF_BASE (0x8000) #define RXBUF_BASE (0xc000) From c2eaf566349b7aadc0c25ca9817e881b50e606cb Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 12:36:12 +1100 Subject: [PATCH 0781/1299] stm32/Makefile: Enable max buffer size on W5200 NIC when used with lwIP. Because in network_wiznet5k the TX/RX buffers are set to 16k each when in MACRAW mode, which is used with lwIP. --- ports/stm32/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 61ce06ca8c8a7..c9fdc7b0d2bf5 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -408,6 +408,10 @@ ifneq ($(MICROPY_PY_WIZNET5K),0) WIZNET5K_DIR=drivers/wiznet5k INC += -I$(TOP)/$(WIZNET5K_DIR) CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=$(MICROPY_PY_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_WIZNET5K) +ifeq ($(MICROPY_PY_LWIP),1) +# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket +CFLAGS_MOD += -DWIZCHIP_USE_MAX_BUFFER +endif SRC_MOD += network_wiznet5k.c modnwwiznet5k.c SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ ethernet/w$(MICROPY_PY_WIZNET5K)/w$(MICROPY_PY_WIZNET5K).c \ From 48e9262f550ba8c5ff2d7c48c8f8c7f7e5ccfec6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 13:29:11 +1100 Subject: [PATCH 0782/1299] py/dynruntime: Implement uint new/get, mp_obj_len and mp_obj_subscr. --- py/dynruntime.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/py/dynruntime.h b/py/dynruntime.h index a83aa905c114e..7092a5dd888cc 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -97,6 +97,7 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_obj_new_bool(b) ((b) ? (mp_obj_t)mp_fun_table.const_true : (mp_obj_t)mp_fun_table.const_false) #define mp_obj_new_int(i) (mp_fun_table.native_to_obj(i, MP_NATIVE_TYPE_INT)) +#define mp_obj_new_int_from_uint(i) (mp_fun_table.native_to_obj(i, MP_NATIVE_TYPE_UINT)) #define mp_obj_new_str(data, len) (mp_fun_table.obj_new_str((data), (len))) #define mp_obj_new_str_of_type(t, d, l) (mp_obj_new_str_of_type_dyn((t), (d), (l))) #define mp_obj_new_bytes(data, len) (mp_fun_table.obj_new_bytes((data), (len))) @@ -106,11 +107,14 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_obj_get_type(o) (mp_fun_table.obj_get_type((o))) #define mp_obj_get_int(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_INT)) +#define mp_obj_get_int_truncated(o) (mp_fun_table.native_from_obj(o, MP_NATIVE_TYPE_UINT)) #define mp_obj_str_get_str(s) ((void*)mp_fun_table.native_from_obj(s, MP_NATIVE_TYPE_PTR)) #define mp_obj_str_get_data(o, len) (mp_obj_str_get_data_dyn((o), (len))) #define mp_get_buffer_raise(o, bufinfo, fl) (mp_fun_table.get_buffer_raise((o), (bufinfo), (fl))) #define mp_get_stream_raise(s, flags) (mp_fun_table.get_stream_raise((s), (flags))) +#define mp_obj_len(o) (mp_obj_len_dyn(o)) +#define mp_obj_subscr(base, index, val) (mp_fun_table.obj_subscr((base), (index), (val))) #define mp_obj_list_append(list, item) (mp_fun_table.list_append((list), (item))) static inline mp_obj_t mp_obj_new_str_of_type_dyn(const mp_obj_type_t *type, const byte* data, size_t len) { @@ -128,6 +132,11 @@ static inline void *mp_obj_str_get_data_dyn(mp_obj_t o, size_t *l) { return bufinfo.buf; } +static inline mp_obj_t mp_obj_len_dyn(mp_obj_t o) { + // If bytes implemented MP_UNARY_OP_LEN could use: mp_unary_op(MP_UNARY_OP_LEN, o) + return mp_fun_table.call_function_n_kw(mp_fun_table.load_name(MP_QSTR_len), 1, &o); +} + /******************************************************************************/ // General runtime functions From ba84453f77ed8ce5e8ac128bee80d3923a14e9ad Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 13:30:44 +1100 Subject: [PATCH 0783/1299] examples/natmod: Add urandom native module example. --- examples/natmod/urandom/Makefile | 13 ++++++++++++ examples/natmod/urandom/urandom.c | 34 +++++++++++++++++++++++++++++++ extmod/modurandom.c | 4 ++++ tests/run-natmodtests.py | 1 + 4 files changed, 52 insertions(+) create mode 100644 examples/natmod/urandom/Makefile create mode 100644 examples/natmod/urandom/urandom.c diff --git a/examples/natmod/urandom/Makefile b/examples/natmod/urandom/Makefile new file mode 100644 index 0000000000000..3f018baaf76b6 --- /dev/null +++ b/examples/natmod/urandom/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in urandom so it can coexist) +MOD = urandom_$(ARCH) + +# Source files (.c or .py) +SRC = urandom.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/urandom/urandom.c b/examples/natmod/urandom/urandom.c new file mode 100644 index 0000000000000..732e439eeab5c --- /dev/null +++ b/examples/natmod/urandom/urandom.c @@ -0,0 +1,34 @@ +#define MICROPY_ENABLE_DYNRUNTIME (1) +#define MICROPY_PY_URANDOM (1) +#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) + +#include "py/dynruntime.h" + +// Dynamic native modules don't support a data section so these must go in the BSS +uint32_t yasmarang_pad, yasmarang_n, yasmarang_d; +uint8_t yasmarang_dat; + +#include "extmod/modurandom.c" + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + yasmarang_pad = 0xeda4baba; + yasmarang_n = 69; + yasmarang_d = 233; + + mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom)); + mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj)); + mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj)); + #if MICROPY_PY_URANDOM_EXTRA_FUNCS + mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj)); + mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj)); + mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj)); + #if MICROPY_PY_BUILTINS_FLOAT + mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj)); + mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj)); + #endif + #endif + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/extmod/modurandom.c b/extmod/modurandom.c index 2e667570d65ce..e3c7fc7f5974c 100644 --- a/extmod/modurandom.c +++ b/extmod/modurandom.c @@ -36,8 +36,10 @@ // http://www.literatecode.com/yasmarang // Public Domain +#if !MICROPY_ENABLE_DYNRUNTIME STATIC uint32_t yasmarang_pad = 0xeda4baba, yasmarang_n = 69, yasmarang_d = 233; STATIC uint8_t yasmarang_dat = 0; +#endif STATIC uint32_t yasmarang(void) { @@ -208,6 +210,7 @@ STATIC mp_obj_t mod_urandom___init__() { STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom___init___obj, mod_urandom___init__); #endif +#if !MICROPY_ENABLE_DYNRUNTIME STATIC const mp_rom_map_elem_t mp_module_urandom_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_urandom) }, #ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC @@ -232,5 +235,6 @@ const mp_obj_module_t mp_module_urandom = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_urandom_globals, }; +#endif #endif //MICROPY_PY_URANDOM diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py index 186c30b83162e..3f49a1d68ae85 100755 --- a/tests/run-natmodtests.py +++ b/tests/run-natmodtests.py @@ -23,6 +23,7 @@ 'btree': 'btree/btree_$(ARCH).mpy', 'framebuf': 'framebuf/framebuf_$(ARCH).mpy', 'uheapq': 'uheapq/uheapq_$(ARCH).mpy', + 'urandom': 'urandom/urandom_$(ARCH).mpy', 'ure': 'ure/ure_$(ARCH).mpy', 'uzlib': 'uzlib/uzlib_$(ARCH).mpy', } From 4da763fc49af5d7c6bbcd1af89135320022bffd0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 13:32:15 +1100 Subject: [PATCH 0784/1299] travis: Build urandom native module in coverage job. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index fef8bbbcfb062..36998300db362 100644 --- a/.travis.yml +++ b/.travis.yml @@ -87,6 +87,7 @@ jobs: - make -C examples/natmod/btree ARCH=x64 - make -C examples/natmod/framebuf ARCH=x64 - make -C examples/natmod/uheapq ARCH=x64 + - make -C examples/natmod/urandom ARCH=x64 - make -C examples/natmod/ure ARCH=x64 - make -C examples/natmod/uzlib ARCH=x64 # test importing .mpy generated by mpy_ld.py From 624f4ca39bbbf9c89fce24f4051dcdd9417e59b1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 13:49:34 +1100 Subject: [PATCH 0785/1299] tests: Add .exp files for basics/parser and import/import_override. Because CPython 3.8.0 now produces different output: - basics/parser.py: CPython does not allow '\\\n' as input. - import/import_override: CPython imports _io. --- tests/basics/parser.py.exp | 3 +++ tests/import/import_override.py.exp | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 tests/basics/parser.py.exp create mode 100644 tests/import/import_override.py.exp diff --git a/tests/basics/parser.py.exp b/tests/basics/parser.py.exp new file mode 100644 index 0000000000000..4d9886a09c096 --- /dev/null +++ b/tests/basics/parser.py.exp @@ -0,0 +1,3 @@ +SyntaxError +SyntaxError +SyntaxError diff --git a/tests/import/import_override.py.exp b/tests/import/import_override.py.exp new file mode 100644 index 0000000000000..365248da6d847 --- /dev/null +++ b/tests/import/import_override.py.exp @@ -0,0 +1,2 @@ +import import1b None 0 +456 From 71c6bfd08a91c942decbfd659cafd2773afb00b4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 14:18:55 +1100 Subject: [PATCH 0786/1299] stm32/modusocket: Handle case of NULL NIC in socket ioctl. --- ports/stm32/modusocket.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/stm32/modusocket.c b/ports/stm32/modusocket.c index 46d7240ca88b9..9af6e371f0a80 100644 --- a/ports/stm32/modusocket.c +++ b/ports/stm32/modusocket.c @@ -369,6 +369,13 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int * } return 0; } + if (self->nic == MP_OBJ_NULL) { + if (request == MP_STREAM_POLL) { + return MP_STREAM_POLL_NVAL; + } + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } return self->nic_type->ioctl(self, request, arg, errcode); } From 33b0a7e6019a7058d2eab3c9623096d4b6f7f6b7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 14:49:16 +1100 Subject: [PATCH 0787/1299] tests/stress/qstr_limit: Tune params to run with stm32 port. Because MICROPY_ALLOC_PATH_MAX is only 128 for this port. --- tests/stress/qstr_limit.py | 12 +++++------- tests/stress/qstr_limit.py.exp | 10 +++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/tests/stress/qstr_limit.py b/tests/stress/qstr_limit.py index 90c85dae962fe..889ab7e51c09b 100644 --- a/tests/stress/qstr_limit.py +++ b/tests/stress/qstr_limit.py @@ -64,19 +64,17 @@ class A: print('RuntimeError', l) # import module -# (different OS's have different results so only print those that are consistent) -for l in range(150, 259): +# (different OS's have different results so only run those that are consistent) +for l in (100, 101, 256, 257, 258): try: __import__(make_id(l)) except ImportError: - if l < 152: - print('ok', l) + print('ok', l) except RuntimeError: - if l > 255: - print('RuntimeError', l) + print('RuntimeError', l) # import package -for l in range(125, 130): +for l in (100, 101, 102, 128, 129): try: exec('import ' + make_id(l) + '.' + make_id(l, 'A')) except ImportError: diff --git a/tests/stress/qstr_limit.py.exp b/tests/stress/qstr_limit.py.exp index 516c9d7f6c16b..455761bc71e4a 100644 --- a/tests/stress/qstr_limit.py.exp +++ b/tests/stress/qstr_limit.py.exp @@ -31,13 +31,13 @@ RuntimeError 258 RuntimeError 256 RuntimeError 257 RuntimeError 258 -ok 150 -ok 151 +ok 100 +ok 101 RuntimeError 256 RuntimeError 257 RuntimeError 258 -ok 125 -ok 126 -ok 127 +ok 100 +ok 101 +ok 102 RuntimeError 128 RuntimeError 129 From 1098d1d630105cc64aae1175a6cc3f40054ba048 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 15:38:03 +1100 Subject: [PATCH 0788/1299] tests/basics/memoryview_itemsize: Make portable to 32- and 64-bit archs. --- tests/basics/memoryview_itemsize.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/basics/memoryview_itemsize.py b/tests/basics/memoryview_itemsize.py index cd7a87c23dfea..64a8822b8b214 100644 --- a/tests/basics/memoryview_itemsize.py +++ b/tests/basics/memoryview_itemsize.py @@ -12,9 +12,12 @@ print("SKIP") raise SystemExit -for code in ['b', 'h', 'i', 'l', 'q', 'f', 'd']: +for code in ['b', 'h', 'i', 'q', 'f', 'd']: print(memoryview(array(code)).itemsize) +# 'l' varies depending on word size of the machine +print(memoryview(array('l')).itemsize in (4, 8)) + # shouldn't be able to store to the itemsize attribute try: memoryview(b'a').itemsize = 1 From 7280bf40d9b43118cca87a7321c088e118a5ebc1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 15:38:45 +1100 Subject: [PATCH 0789/1299] tests/extmod/vfs_lfs_error: Use small ints in seek error test. So accessing the seek offset (at the C level) doesn't cause an OverflowError on 32-bit targets. --- tests/extmod/vfs_lfs_error.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/extmod/vfs_lfs_error.py b/tests/extmod/vfs_lfs_error.py index b97fe6ec159b4..793fae59e2beb 100644 --- a/tests/extmod/vfs_lfs_error.py +++ b/tests/extmod/vfs_lfs_error.py @@ -106,8 +106,9 @@ def test(bdev, vfs_class): # error during seek with vfs.open('testfile', 'r') as f: + f.seek(1 << 30) # SEEK_SET try: - f.seek(1 << 31) + f.seek(1 << 30, 1) # SEEK_CUR except OSError: print('seek OSError') From 4b184d12819139fc51073248614111c45a5ac631 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 16:43:17 +1100 Subject: [PATCH 0790/1299] tests/pyb: Refactor pyboard tests to work on PYBv1, PYBLITEv1 and PYBD. --- tests/pyb/accel.py | 4 ++++ tests/pyb/adc.py | 2 +- tests/pyb/adc.py.exp | 2 +- tests/pyb/board_pybv1x.py | 39 +++++++++++++++++++++++++++++++++++ tests/pyb/board_pybv1x.py.exp | 29 ++++++++++++++++++++++++++ tests/pyb/can.py | 25 +++++++--------------- tests/pyb/can.py.exp | 9 +------- tests/pyb/can2.py | 24 +++++++++++++++++++++ tests/pyb/can2.py.exp | 4 ++++ tests/pyb/extint.py | 2 +- tests/pyb/extint.py.exp | 6 +++--- tests/pyb/halerror.py | 15 -------------- tests/pyb/halerror.py.exp | 2 -- tests/pyb/i2c.py | 20 ++---------------- tests/pyb/i2c.py.exp | 8 ------- tests/pyb/i2c_accel.py | 23 +++++++++++++++++++++ tests/pyb/i2c_accel.py.exp | 3 +++ tests/pyb/i2c_error.py | 4 ++++ tests/pyb/led.py | 24 +++++++++++---------- tests/pyb/led.py.exp | 1 - tests/pyb/pin.py | 8 +++---- tests/pyb/pin.py.exp | 12 +++++------ tests/pyb/pyb_f405.py | 8 +++++++ tests/pyb/pyb_f405.py.exp | 1 + tests/pyb/spi.py | 6 +++--- tests/pyb/spi.py.exp | 6 +----- tests/pyb/uart.py | 4 ++-- tests/pyb/uart.py.exp | 7 ------- 28 files changed, 185 insertions(+), 113 deletions(-) create mode 100644 tests/pyb/board_pybv1x.py create mode 100644 tests/pyb/board_pybv1x.py.exp create mode 100644 tests/pyb/can2.py create mode 100644 tests/pyb/can2.py.exp delete mode 100644 tests/pyb/halerror.py delete mode 100644 tests/pyb/halerror.py.exp create mode 100644 tests/pyb/i2c_accel.py create mode 100644 tests/pyb/i2c_accel.py.exp diff --git a/tests/pyb/accel.py b/tests/pyb/accel.py index e5a1a2ed7a441..9aa60c1859e9f 100644 --- a/tests/pyb/accel.py +++ b/tests/pyb/accel.py @@ -1,5 +1,9 @@ import pyb +if not hasattr(pyb, 'Accel'): + print('SKIP') + raise SystemExit + accel = pyb.Accel() print(accel) accel.x() diff --git a/tests/pyb/adc.py b/tests/pyb/adc.py index 0bd9b9d53a5ca..ef420653888d3 100644 --- a/tests/pyb/adc.py +++ b/tests/pyb/adc.py @@ -1,7 +1,7 @@ from pyb import ADC, Timer adct = ADC(16) # Temperature 930 -> 20C -print(adct) +print(str(adct)[:19]) adcv = ADC(17) # Voltage 1500 -> 3.3V print(adcv) diff --git a/tests/pyb/adc.py.exp b/tests/pyb/adc.py.exp index 1aae16fb01771..381329cdde046 100644 --- a/tests/pyb/adc.py.exp +++ b/tests/pyb/adc.py.exp @@ -1,4 +1,4 @@ - + 50 25 diff --git a/tests/pyb/board_pybv1x.py b/tests/pyb/board_pybv1x.py new file mode 100644 index 0000000000000..f4aeeb99eb482 --- /dev/null +++ b/tests/pyb/board_pybv1x.py @@ -0,0 +1,39 @@ +# Test board-specific items on PYBv1.x + +import os, pyb + +if not 'PYBv1.' in os.uname().machine: + print('SKIP') + raise SystemExit + +# test creating UART by id/name +for bus in (1, 2, 3, 4, 5, 6, 7, "XA", "XB", "YA", "YB", "Z"): + try: + pyb.UART(bus, 9600) + print("UART", bus) + except ValueError: + print("ValueError", bus) + +# test creating SPI by id/name +for bus in (1, 2, 3, "X", "Y", "Z"): + try: + pyb.SPI(bus) + print("SPI", bus) + except ValueError: + print("ValueError", bus) + +# test creating I2C by id/name +for bus in (2, 3, "X", "Y", "Z"): + try: + pyb.I2C(bus) + print("I2C", bus) + except ValueError: + print("ValueError", bus) + +# test creating CAN by id/name +for bus in (1, 2, 3, "YA", "YB", "YC"): + try: + pyb.CAN(bus, pyb.CAN.LOOPBACK) + print("CAN", bus) + except ValueError: + print("ValueError", bus) diff --git a/tests/pyb/board_pybv1x.py.exp b/tests/pyb/board_pybv1x.py.exp new file mode 100644 index 0000000000000..6d4a6f63c7434 --- /dev/null +++ b/tests/pyb/board_pybv1x.py.exp @@ -0,0 +1,29 @@ +UART 1 +UART 2 +UART 3 +UART 4 +ValueError 5 +UART 6 +ValueError 7 +UART XA +UART XB +UART YA +UART YB +ValueError Z +SPI 1 +SPI 2 +ValueError 3 +SPI X +SPI Y +ValueError Z +I2C 2 +ValueError 3 +I2C X +I2C Y +ValueError Z +CAN 1 +CAN 2 +ValueError 3 +CAN YA +CAN YB +ValueError YC diff --git a/tests/pyb/can.py b/tests/pyb/can.py index 8a08ea9a65b3c..71de724c76349 100644 --- a/tests/pyb/can.py +++ b/tests/pyb/can.py @@ -8,8 +8,8 @@ import micropython import pyb -# test we can correctly create by id or name -for bus in (-1, 0, 1, 2, 3, "YA", "YB", "YC"): +# test we can correctly create by id (2 handled in can2.py test) +for bus in (-1, 0, 1, 3): try: CAN(bus, CAN.LOOPBACK) print("CAN", bus) @@ -273,18 +273,11 @@ def cb1a(bus, reason): # Testing rtr messages bus1 = CAN(1, CAN.LOOPBACK) -bus2 = CAN(2, CAN.LOOPBACK, extframe = True) while bus1.any(0): bus1.recv(0) -while bus2.any(0): - bus2.recv(0) bus1.setfilter(0, CAN.LIST16, 0, (1, 2, 3, 4)) bus1.setfilter(1, CAN.LIST16, 0, (5, 6, 7, 8), rtr=(True, True, True, True)) bus1.setfilter(2, CAN.MASK16, 0, (64, 64, 32, 32), rtr=(False, True)) -bus2.setfilter(0, CAN.LIST32, 0, (1, 2), rtr=(True, True)) -bus2.setfilter(1, CAN.LIST32, 0, (3, 4), rtr=(True, False)) -bus2.setfilter(2, CAN.MASK32, 0, (16, 16), rtr=(False,)) -bus2.setfilter(2, CAN.MASK32, 0, (32, 32), rtr=(True,)) bus1.send('',1,rtr=True) print(bus1.any(0)) @@ -299,11 +292,9 @@ def cb1a(bus, reason): bus1.send('',32,rtr=True) print(bus1.recv(0)) -bus2.send('',1,rtr=True) -print(bus2.recv(0)) -bus2.send('',2,rtr=True) -print(bus2.recv(0)) -bus2.send('',3,rtr=True) -print(bus2.recv(0)) -bus2.send('',4,rtr=True) -print(bus2.any(0)) +# test HAL error, timeout +can = pyb.CAN(1, pyb.CAN.NORMAL) +try: + can.send('1', 1, timeout=50) +except OSError as e: + print(repr(e)) diff --git a/tests/pyb/can.py.exp b/tests/pyb/can.py.exp index 687935e7f45bc..a27907cc52389 100644 --- a/tests/pyb/can.py.exp +++ b/tests/pyb/can.py.exp @@ -1,11 +1,7 @@ ValueError -1 ValueError 0 CAN 1 -CAN 2 ValueError 3 -CAN YA -CAN YB -ValueError YC CAN(1) True CAN(1, CAN.LOOPBACK, extframe=False, auto_restart=False) @@ -70,7 +66,4 @@ False (7, True, 6, b'') False (32, True, 9, b'') -(1, True, 0, b'') -(2, True, 1, b'') -(3, True, 2, b'') -False +OSError(110,) diff --git a/tests/pyb/can2.py b/tests/pyb/can2.py new file mode 100644 index 0000000000000..440ae4925b3e1 --- /dev/null +++ b/tests/pyb/can2.py @@ -0,0 +1,24 @@ +try: + from pyb import CAN + CAN(2) +except (ImportError, ValueError): + print('SKIP') + raise SystemExit + +# Testing rtr messages +bus2 = CAN(2, CAN.LOOPBACK, extframe=True) +while bus2.any(0): + bus2.recv(0) +bus2.setfilter(0, CAN.LIST32, 0, (1, 2), rtr=(True, True)) +bus2.setfilter(1, CAN.LIST32, 0, (3, 4), rtr=(True, False)) +bus2.setfilter(2, CAN.MASK32, 0, (16, 16), rtr=(False,)) +bus2.setfilter(2, CAN.MASK32, 0, (32, 32), rtr=(True,)) + +bus2.send('',1,rtr=True) +print(bus2.recv(0)) +bus2.send('',2,rtr=True) +print(bus2.recv(0)) +bus2.send('',3,rtr=True) +print(bus2.recv(0)) +bus2.send('',4,rtr=True) +print(bus2.any(0)) diff --git a/tests/pyb/can2.py.exp b/tests/pyb/can2.py.exp new file mode 100644 index 0000000000000..371ad2bdc435b --- /dev/null +++ b/tests/pyb/can2.py.exp @@ -0,0 +1,4 @@ +(1, True, 0, b'') +(2, True, 1, b'') +(3, True, 2, b'') +False diff --git a/tests/pyb/extint.py b/tests/pyb/extint.py index ae98ccd5a0de5..8b6bc565178e1 100644 --- a/tests/pyb/extint.py +++ b/tests/pyb/extint.py @@ -1,7 +1,7 @@ import pyb # test basic functionality -ext = pyb.ExtInt('Y1', pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_DOWN, lambda l:print('line:', l)) +ext = pyb.ExtInt('X5', pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_DOWN, lambda l:print('line:', l)) ext.disable() ext.enable() print(ext.line()) diff --git a/tests/pyb/extint.py.exp b/tests/pyb/extint.py.exp index 1f9da9844a081..fbd820ed43a34 100644 --- a/tests/pyb/extint.py.exp +++ b/tests/pyb/extint.py.exp @@ -1,3 +1,3 @@ -6 -line: 6 -line: 6 +4 +line: 4 +line: 4 diff --git a/tests/pyb/halerror.py b/tests/pyb/halerror.py deleted file mode 100644 index 1a6bce1a7ef9d..0000000000000 --- a/tests/pyb/halerror.py +++ /dev/null @@ -1,15 +0,0 @@ -# test hal errors - -import pyb - -i2c = pyb.I2C(2, pyb.I2C.MASTER) -try: - i2c.recv(1, 1) -except OSError as e: - print(repr(e)) - -can = pyb.CAN(1, pyb.CAN.NORMAL) -try: - can.send('1', 1, timeout=50) -except OSError as e: - print(repr(e)) diff --git a/tests/pyb/halerror.py.exp b/tests/pyb/halerror.py.exp deleted file mode 100644 index 0f3f26253dc81..0000000000000 --- a/tests/pyb/halerror.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -OSError(5,) -OSError(110,) diff --git a/tests/pyb/i2c.py b/tests/pyb/i2c.py index 6875e5a5aa024..bc9dba8781aa9 100644 --- a/tests/pyb/i2c.py +++ b/tests/pyb/i2c.py @@ -1,8 +1,8 @@ import pyb from pyb import I2C -# test we can correctly create by id or name -for bus in (-1, 0, 1, 2, 3, "X", "Y", "Z"): +# test we can correctly create by id +for bus in (-1, 0, 1): try: I2C(bus) print("I2C", bus) @@ -14,19 +14,3 @@ i2c.init(I2C.MASTER, baudrate=400000) print(i2c.scan()) i2c.deinit() - -# use accelerometer to test i2c bus - -accel_addr = 76 - -pyb.Accel() # this will init the MMA for us -i2c.init(I2C.MASTER, baudrate=400000) - -print(i2c.scan()) -print(i2c.is_ready(accel_addr)) - -print(i2c.mem_read(1, accel_addr, 7, timeout=500)) -i2c.mem_write(0, accel_addr, 0, timeout=500) - -i2c.send(7, addr=accel_addr) -i2c.recv(1, addr=accel_addr) diff --git a/tests/pyb/i2c.py.exp b/tests/pyb/i2c.py.exp index 709fb412de978..bd896ea74e4b9 100644 --- a/tests/pyb/i2c.py.exp +++ b/tests/pyb/i2c.py.exp @@ -1,12 +1,4 @@ ValueError -1 ValueError 0 I2C 1 -I2C 2 -ValueError 3 -I2C X -I2C Y -ValueError Z [] -[76] -True -b'\x01' diff --git a/tests/pyb/i2c_accel.py b/tests/pyb/i2c_accel.py new file mode 100644 index 0000000000000..e42cba178a844 --- /dev/null +++ b/tests/pyb/i2c_accel.py @@ -0,0 +1,23 @@ +# use accelerometer to test i2c bus + +import pyb +from pyb import I2C + +if not hasattr(pyb, 'Accel'): + print('SKIP') + raise SystemExit + +accel_addr = 76 + +pyb.Accel() # this will init the MMA for us + +i2c = I2C(1, I2C.MASTER, baudrate=400000) + +print(i2c.scan()) +print(i2c.is_ready(accel_addr)) + +print(i2c.mem_read(1, accel_addr, 7, timeout=500)) +i2c.mem_write(0, accel_addr, 0, timeout=500) + +i2c.send(7, addr=accel_addr) +i2c.recv(1, addr=accel_addr) diff --git a/tests/pyb/i2c_accel.py.exp b/tests/pyb/i2c_accel.py.exp new file mode 100644 index 0000000000000..206a2eb4c2a95 --- /dev/null +++ b/tests/pyb/i2c_accel.py.exp @@ -0,0 +1,3 @@ +[76] +True +b'\x01' diff --git a/tests/pyb/i2c_error.py b/tests/pyb/i2c_error.py index 3201d6367dbeb..e0f721179f452 100644 --- a/tests/pyb/i2c_error.py +++ b/tests/pyb/i2c_error.py @@ -3,6 +3,10 @@ import pyb from pyb import I2C +if not hasattr(pyb, 'Accel'): + print('SKIP') + raise SystemExit + # init accelerometer pyb.Accel() diff --git a/tests/pyb/led.py b/tests/pyb/led.py index d2a17ebc9adfc..38e9993cb0083 100644 --- a/tests/pyb/led.py +++ b/tests/pyb/led.py @@ -1,17 +1,19 @@ -import pyb -from pyb import LED +import os, pyb -l1 = pyb.LED(1) -l2 = pyb.LED(2) -l3 = pyb.LED(3) -l4 = pyb.LED(4) - -leds = [LED(i) for i in range(1, 5)] -pwm_leds = leds[2:] +machine = os.uname().machine +if 'PYBv1.' in machine or 'PYBLITEv1.' in machine: + leds = [pyb.LED(i) for i in range(1, 5)] + pwm_leds = leds[2:] +elif 'PYBD' in machine: + leds = [pyb.LED(i) for i in range(1, 4)] + pwm_leds = [] +else: + print('SKIP') + raise SystemExit # test printing -for l in leds: - print(l) +for i in range(3): + print(leds[i]) # test on and off for l in leds: diff --git a/tests/pyb/led.py.exp b/tests/pyb/led.py.exp index 4e8d856cd94b0..b4170c41e4403 100644 --- a/tests/pyb/led.py.exp +++ b/tests/pyb/led.py.exp @@ -1,4 +1,3 @@ LED(1) LED(2) LED(3) -LED(4) diff --git a/tests/pyb/pin.py b/tests/pyb/pin.py index 9b37883438f33..ea42cc206ffca 100644 --- a/tests/pyb/pin.py +++ b/tests/pyb/pin.py @@ -1,14 +1,14 @@ from pyb import Pin -p = Pin('Y1', Pin.IN) +p = Pin('X8', Pin.IN) print(p) print(p.name()) print(p.pin()) print(p.port()) -p = Pin('Y1', Pin.IN, Pin.PULL_UP) -p = Pin('Y1', Pin.IN, pull=Pin.PULL_UP) -p = Pin('Y1', mode=Pin.IN, pull=Pin.PULL_UP) +p = Pin('X8', Pin.IN, Pin.PULL_UP) +p = Pin('X8', Pin.IN, pull=Pin.PULL_UP) +p = Pin('X8', mode=Pin.IN, pull=Pin.PULL_UP) print(p) print(p.value()) diff --git a/tests/pyb/pin.py.exp b/tests/pyb/pin.py.exp index f2f7038fd44b5..a2a7e42d96d18 100644 --- a/tests/pyb/pin.py.exp +++ b/tests/pyb/pin.py.exp @@ -1,10 +1,10 @@ -Pin(Pin.cpu.C6, mode=Pin.IN) -C6 -6 -2 -Pin(Pin.cpu.C6, mode=Pin.IN, pull=Pin.PULL_UP) +Pin(Pin.cpu.A7, mode=Pin.IN) +A7 +7 +0 +Pin(Pin.cpu.A7, mode=Pin.IN, pull=Pin.PULL_UP) 1 -Pin(Pin.cpu.C6, mode=Pin.IN, pull=Pin.PULL_DOWN) +Pin(Pin.cpu.A7, mode=Pin.IN, pull=Pin.PULL_DOWN) 0 0 1 diff --git a/tests/pyb/pyb_f405.py b/tests/pyb/pyb_f405.py index 2f161ae099592..f49dd1bc75aee 100644 --- a/tests/pyb/pyb_f405.py +++ b/tests/pyb/pyb_f405.py @@ -8,3 +8,11 @@ print(pyb.freq()) print(type(pyb.rng())) + +# test HAL error specific to F405 +i2c = pyb.I2C(2, pyb.I2C.MASTER) +try: + i2c.recv(1, 1) +except OSError as e: + print(repr(e)) + diff --git a/tests/pyb/pyb_f405.py.exp b/tests/pyb/pyb_f405.py.exp index a90aa0268659e..a52f40920d111 100644 --- a/tests/pyb/pyb_f405.py.exp +++ b/tests/pyb/pyb_f405.py.exp @@ -1,2 +1,3 @@ (168000000, 168000000, 42000000, 84000000) +OSError(5,) diff --git a/tests/pyb/spi.py b/tests/pyb/spi.py index 88cc975bb6602..577737420fc98 100644 --- a/tests/pyb/spi.py +++ b/tests/pyb/spi.py @@ -1,7 +1,7 @@ from pyb import SPI -# test we can correctly create by id or name -for bus in (-1, 0, 1, 2, 3, "X", "Y", "Z"): +# test we can correctly create by id +for bus in (-1, 0, 1, 2): try: SPI(bus) print("SPI", bus) @@ -14,7 +14,7 @@ spi = SPI(1, SPI.MASTER) spi = SPI(1, SPI.MASTER, baudrate=500000) spi = SPI(1, SPI.MASTER, 500000, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None) -print(spi) +print(str(spi)[:28], str(spi)[49:]) # don't print baudrate/prescaler spi.init(SPI.SLAVE, phase=1) print(spi) diff --git a/tests/pyb/spi.py.exp b/tests/pyb/spi.py.exp index a0d835700f073..473c173a58d8b 100644 --- a/tests/pyb/spi.py.exp +++ b/tests/pyb/spi.py.exp @@ -2,12 +2,8 @@ ValueError -1 ValueError 0 SPI 1 SPI 2 -ValueError 3 -SPI X -SPI Y -ValueError Z SPI(1) -SPI(1, SPI.MASTER, baudrate=328125, prescaler=256, polarity=1, phase=0, bits=8) +SPI(1, SPI.MASTER, baudrate= , polarity=1, phase=0, bits=8) SPI(1, SPI.SLAVE, polarity=1, phase=1, bits=8) OSError b'\xff' diff --git a/tests/pyb/uart.py b/tests/pyb/uart.py index 836b073a6d952..82a66dd2e05de 100644 --- a/tests/pyb/uart.py +++ b/tests/pyb/uart.py @@ -1,7 +1,7 @@ from pyb import UART -# test we can correctly create by id or name -for bus in (-1, 0, 1, 2, 3, 4, 5, 6, 7, "XA", "XB", "YA", "YB", "Z"): +# test we can correctly create by id +for bus in (-1, 0, 1, 2, 5, 6, 7): try: UART(bus, 9600) print("UART", bus) diff --git a/tests/pyb/uart.py.exp b/tests/pyb/uart.py.exp index d302468ed2c26..1a4cbd9381e84 100644 --- a/tests/pyb/uart.py.exp +++ b/tests/pyb/uart.py.exp @@ -2,16 +2,9 @@ ValueError -1 ValueError 0 UART 1 UART 2 -UART 3 -UART 4 ValueError 5 UART 6 ValueError 7 -UART XA -UART XB -UART YA -UART YB -ValueError Z UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=64) UART(1, baudrate=2400, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=7, rxbuf=64) 0 From fb014155996c7568eb55ab06fdeaf6ff414f0280 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 13 Dec 2019 17:26:30 +1100 Subject: [PATCH 0791/1299] stm32/boards/PYBD_SF2: Configure LEDs as inverted, for LED.intensity(). --- ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index 8e116bd02a59e..4ce17abd870c1 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -154,6 +154,7 @@ extern struct _spi_bdev_t spi_bdev2; #define MICROPY_HW_USRSW_PRESSED (0) // LEDs +#define MICROPY_HW_LED_INVERTED (1) // LEDs are on when pin is driven low #define MICROPY_HW_LED1 (pyb_pin_LED_RED) #define MICROPY_HW_LED2 (pyb_pin_LED_GREEN) #define MICROPY_HW_LED3 (pyb_pin_LED_BLUE) From f3f7eb48da8bbd108e18103a45f9898846d6eb48 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 16 Dec 2019 12:38:27 +1100 Subject: [PATCH 0792/1299] docs/library/uos.rst: Clarify why the extended interface exists. --- docs/library/uos.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/library/uos.rst b/docs/library/uos.rst index 5505e6434ff28..bb7e491cce908 100644 --- a/docs/library/uos.rst +++ b/docs/library/uos.rst @@ -234,6 +234,10 @@ methods (see below), in order to support a variety of use cases. A given block device may implement one form or the other, or both at the same time. The second form (with the offset parameter) is referred to as the "extended interface". +Some filesystems (such as littlefs) that require more control over write +operations, for example writing to sub-block regions without erasing, may require +that the block device supports the extended interface. + .. class:: AbstractBlockDev(...) Construct a block device object. The parameters to the constructor are From 04e7aa056316d7b4400b508caefe26c6b75384f8 Mon Sep 17 00:00:00 2001 From: ketograph Date: Sat, 14 Dec 2019 16:56:14 +0100 Subject: [PATCH 0793/1299] docs/esp8266/quickref: Add note that machine.RTC is not fully supported. See issues #3220 and #3710. --- docs/esp8266/quickref.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index a1976650436ce..9c7db3205a7e6 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -249,6 +249,10 @@ See :ref:`machine.RTC ` :: ntptime.settime() # set the rtc datetime from the remote server rtc.datetime() # get the date and time in UTC +.. note:: Not all methods are implemented: `RTC.now()`, `RTC.irq(handler=*) ` + (using a custom handler), `RTC.init()` and `RTC.deinit()` are + currently not supported. + Deep-sleep mode --------------- From 0bd7d1f7f03d086a0789caa8e007cf15068c689c Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Dec 2019 21:53:43 +1100 Subject: [PATCH 0794/1299] py/persistentcode: Move loading of rodata/bss to before obj/raw-code. This makes the loading of viper-code-with-relocations a bit neater and easier to understand, by treating the rodata/bss like a special object to be loaded into the constant table (which is how it behaves). --- py/persistentcode.c | 39 +++++++++++++++++++++++++++------------ tools/mpy_ld.py | 16 +--------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/py/persistentcode.c b/py/persistentcode.c index 8bf46202ba63a..7a8a94b5a64a2 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -438,9 +438,18 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { // Allocate constant table size_t n_alloc = prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code; + #if MICROPY_EMIT_MACHINE_CODE if (kind != MP_CODE_BYTECODE) { ++n_alloc; // additional entry for mp_fun_table + if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) { + ++n_alloc; // additional entry for rodata + } + if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) { + ++n_alloc; // additional entry for BSS + } } + #endif + const_table = m_new(mp_uint_t, n_alloc); mp_uint_t *ct = const_table; @@ -454,6 +463,21 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { if (kind != MP_CODE_BYTECODE) { // Populate mp_fun_table entry *ct++ = (mp_uint_t)(uintptr_t)&mp_fun_table; + + // Allocate and load rodata if needed + if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) { + size_t size = read_uint(reader, NULL); + uint8_t *rodata = m_new(uint8_t, size); + read_bytes(reader, rodata, size); + *ct++ = (uintptr_t)rodata; + } + + // Allocate BSS if needed + if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) { + size_t size = read_uint(reader, NULL); + uint8_t *bss = m_new0(uint8_t, size); + *ct++ = (uintptr_t)bss; + } } #endif @@ -469,6 +493,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { // Create raw_code and return it mp_raw_code_t *rc = mp_emit_glue_new_raw_code(); if (kind == MP_CODE_BYTECODE) { + // Assign bytecode to raw code object mp_emit_glue_assign_bytecode(rc, fun_data, #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS fun_data_len, @@ -481,18 +506,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { #if MICROPY_EMIT_MACHINE_CODE } else { - mp_uint_t *ct = &const_table[1]; - if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRODATA) { - size_t size = read_uint(reader, NULL); - uint8_t *rodata = m_new(uint8_t, size); - read_bytes(reader, rodata, size); - *ct++ = (uintptr_t)rodata; - } - if (prelude.scope_flags & MP_SCOPE_FLAG_VIPERBSS) { - size_t size = read_uint(reader, NULL); - uint8_t *bss = m_new0(uint8_t, size); - *ct++ = (uintptr_t)bss; - } + // Relocate and commit code to executable address space reloc_info_t ri = {reader, const_table}; #if defined(MP_PLAT_COMMIT_EXEC) void *opt_ri = (prelude.scope_flags & MP_SCOPE_FLAG_VIPERRELOC) ? &ri : NULL; @@ -503,6 +517,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, qstr_window_t *qw) { } #endif + // Assign native code to raw code object mp_emit_glue_assign_native(rc, kind, fun_data, fun_data_len, const_table, #if MICROPY_PERSISTENT_CODE_SAVE diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index ec600f9671d23..31c3912991c48 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -765,14 +765,6 @@ def write_qstr(self, s): self.write_uint(len(s) << 1) self.write_bytes(s) - def write_obj(self, o): - if o is Ellipsis: - self.write_bytes(b'e') - return - else: - # Other Python types not implemented - assert 0 - def write_reloc(self, base, offset, dest, n): need_offset = not (base == self.prev_base and offset == self.prev_offset + 1) self.prev_offset = offset + n - 1 @@ -845,17 +837,11 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): out.write_uint(scope_flags) # MPY: n_obj - out.write_uint(bool(len(env.full_rodata)) + bool(len(env.full_bss))) + out.write_uint(0) # MPY: n_raw_code out.write_uint(0) - # MPY: optional bytes object with rodata - if len(env.full_rodata): - out.write_obj(Ellipsis) - if len(env.full_bss): - out.write_obj(Ellipsis) - # MPY: rodata and/or bss if len(env.full_rodata): rodata_const_table_idx = 1 From 1e2f7515917345ee2937f2870827cf15c29509ab Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 17 Dec 2019 13:18:08 +1100 Subject: [PATCH 0795/1299] qemu-arm: Let tinytest.o be built by standard build rules. This makes sure tinytest.o is rebuilt if any of its dependencies change. --- ports/qemu-arm/Makefile | 5 +---- ports/qemu-arm/Makefile.test | 3 +-- ports/qemu-arm/test_main.c | 5 ++--- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index e06e5dd5eed81..4f12173c3fbe8 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -33,12 +33,9 @@ endif CROSS_COMPILE = arm-none-eabi- -TINYTEST = $(TOP)/lib/tinytest - INC += -I. INC += -I$(TOP) INC += -I$(BUILD) -INC += -I$(TINYTEST) CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 $(COPT) \ -ffunction-sections -fdata-sections @@ -71,6 +68,7 @@ SRC_RUN_C = \ SRC_TEST_C = \ test_main.c \ + lib/tinytest/tinytest.c \ LIB_SRC_C += $(addprefix lib/,\ libc/string0.c \ @@ -108,7 +106,6 @@ ALL_OBJ_RUN = $(OBJ_COMMON) $(OBJ_RUN) OBJ_TEST = OBJ_TEST += $(addprefix $(BUILD)/, $(SRC_TEST_C:.c=.o)) -OBJ_TEST += $(BUILD)/tinytest.o ALL_OBJ_TEST = $(OBJ_COMMON) $(OBJ_TEST) diff --git a/ports/qemu-arm/Makefile.test b/ports/qemu-arm/Makefile.test index df0ba9939dfa6..340e1c3b90d5e 100644 --- a/ports/qemu-arm/Makefile.test +++ b/ports/qemu-arm/Makefile.test @@ -13,8 +13,7 @@ $(BUILD)/genhdr/tests.h: (cd $(TOP)/tests; ./run-tests --target=qemu-arm --write-exp) $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py) > $@ -$(BUILD)/tinytest.o: - $(Q)$(CC) $(CFLAGS) -DNO_FORKING -o $@ -c $(TINYTEST)/tinytest.c +$(BUILD)/lib/tinytest/tinytest.o: CFLAGS += -DNO_FORKING $(BUILD)/firmware-test.elf: $(LDSCRIPT) $(ALL_OBJ_TEST) $(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_TEST) $(LIBS) diff --git a/ports/qemu-arm/test_main.c b/ports/qemu-arm/test_main.c index 3a85d65f38c6a..3fd2c01484784 100644 --- a/ports/qemu-arm/test_main.c +++ b/ports/qemu-arm/test_main.c @@ -12,9 +12,8 @@ #include "py/gc.h" #include "py/mperrno.h" #include "lib/utils/gchelper.h" - -#include "tinytest.h" -#include "tinytest_macros.h" +#include "lib/tinytest/tinytest.h" +#include "lib/tinytest/tinytest_macros.h" #define HEAP_SIZE (100 * 1024) From ba12cdba851f973044c54becca27735a79312707 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 18 Dec 2019 15:04:00 +1100 Subject: [PATCH 0796/1299] examples/network: Add testing key/cert to SSL HTTP server example. This example will now work on all ports with networking and ssl support, with both axtls and mbedtls. --- examples/network/http_server_ssl.py | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/examples/network/http_server_ssl.py b/examples/network/http_server_ssl.py index 9a69ca9d417ea..47d83bf247b2f 100644 --- a/examples/network/http_server_ssl.py +++ b/examples/network/http_server_ssl.py @@ -1,3 +1,4 @@ +import ubinascii as binascii try: import usocket as socket except: @@ -5,6 +6,35 @@ import ussl as ssl +# This self-signed key/cert pair is randomly generated and to be used for +# testing/demonstration only. You should always generate your own key/cert. +key = binascii.unhexlify( + b'3082013b020100024100cc20643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef' + b'610a6a6ba14abb891745cd18a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f' + b'872d0203010001024100bb17a54aeb3dd7ae4edec05e775ca9632cf02d29c2a089b563b0' + b'd05cdf95aeca507de674553f28b4eadaca82d5549a86058f9996b07768686a5b02cb240d' + b'd9f1022100f4a63f5549e817547dca97b5c658038e8593cb78c5aba3c4642cc4cd031d86' + b'8f022100d598d870ffe4a34df8de57047a50b97b71f4d23e323f527837c9edae88c79483' + b'02210098560c89a70385c36eb07fd7083235c4c1184e525d838aedf7128958bedfdbb102' + b'2051c0dab7057a8176ca966f3feb81123d4974a733df0f958525f547dfd1c271f9022044' + b'6c2cafad455a671a8cf398e642e1be3b18a3d3aec2e67a9478f83c964c4f1f') +cert = binascii.unhexlify( + b'308201d53082017f020203e8300d06092a864886f70d01010505003075310b3009060355' + b'0406130258583114301206035504080c0b54686550726f76696e63653110300e06035504' + b'070c075468654369747931133011060355040a0c0a436f6d70616e7958595a3113301106' + b'0355040b0c0a436f6d70616e7958595a3114301206035504030c0b546865486f73744e61' + b'6d65301e170d3139313231383033333935355a170d3239313231353033333935355a3075' + b'310b30090603550406130258583114301206035504080c0b54686550726f76696e636531' + b'10300e06035504070c075468654369747931133011060355040a0c0a436f6d70616e7958' + b'595a31133011060355040b0c0a436f6d70616e7958595a3114301206035504030c0b5468' + b'65486f73744e616d65305c300d06092a864886f70d0101010500034b003048024100cc20' + b'643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef610a6a6ba14abb891745cd18' + b'a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f872d0203010001300d06092a' + b'864886f70d0101050500034100b0513fe2829e9ecbe55b6dd14c0ede7502bde5d46153c8' + b'e960ae3ebc247371b525caeb41bbcf34686015a44c50d226e66aef0a97a63874ca5944ef' + b'979b57f0b3') + + CONTENT = b"""\ HTTP/1.0 200 OK @@ -31,7 +61,8 @@ def main(use_stream=True): client_addr = res[1] print("Client address:", client_addr) print("Client socket:", client_s) - client_s = ssl.wrap_socket(client_s, server_side=True) + # CPython uses key keyfile/certfile arguments, but MicroPython uses key/cert + client_s = ssl.wrap_socket(client_s, server_side=True, key=key, cert=cert) print(client_s) print("Request:") if use_stream: From 0d82f5d8c868d7f4e93d48e400cd4d769175e3e5 Mon Sep 17 00:00:00 2001 From: Seon Rozenblum Date: Thu, 24 Oct 2019 19:20:39 +1100 Subject: [PATCH 0797/1299] esp32/boards/TINYPICO: Add tinypico.py, dotstar.py with custom manifest. --- ports/esp32/boards/TINYPICO/manifest.py | 2 + .../esp32/boards/TINYPICO/modules/dotstar.py | 228 ++++++++++++++++++ .../esp32/boards/TINYPICO/modules/tinypico.py | 113 +++++++++ ports/esp32/boards/TINYPICO/mpconfigboard.mk | 2 + 4 files changed, 345 insertions(+) create mode 100644 ports/esp32/boards/TINYPICO/manifest.py create mode 100644 ports/esp32/boards/TINYPICO/modules/dotstar.py create mode 100644 ports/esp32/boards/TINYPICO/modules/tinypico.py diff --git a/ports/esp32/boards/TINYPICO/manifest.py b/ports/esp32/boards/TINYPICO/manifest.py new file mode 100644 index 0000000000000..81fff1d7c3b98 --- /dev/null +++ b/ports/esp32/boards/TINYPICO/manifest.py @@ -0,0 +1,2 @@ +include('$(PORT_DIR)/boards/manifest.py') +freeze("modules") diff --git a/ports/esp32/boards/TINYPICO/modules/dotstar.py b/ports/esp32/boards/TINYPICO/modules/dotstar.py new file mode 100644 index 0000000000000..a848e8e179615 --- /dev/null +++ b/ports/esp32/boards/TINYPICO/modules/dotstar.py @@ -0,0 +1,228 @@ +# DotStar strip driver for MicroPython +# +# The MIT License (MIT) +# +# Copyright (c) 2016 Damien P. George (original Neopixel object) +# Copyright (c) 2017 Ladyada +# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +# Copyright (c) 2019 Matt Trentini (porting back to MicroPython) +# +# 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. + +START_HEADER_SIZE = 4 +LED_START = 0b11100000 # Three "1" bits, followed by 5 brightness bits + +# Pixel color order constants +RGB = (0, 1, 2) +RBG = (0, 2, 1) +GRB = (1, 0, 2) +GBR = (1, 2, 0) +BRG = (2, 0, 1) +BGR = (2, 1, 0) + + +class DotStar: + """ + A sequence of dotstars. + + :param SPI spi: The SPI object to write output to. + :param int n: The number of dotstars in the chain + :param float brightness: Brightness of the pixels between 0.0 and 1.0 + :param bool auto_write: True if the dotstars should immediately change when + set. If False, `show` must be called explicitly. + :param tuple pixel_order: Set the pixel order on the strip - different + strips implement this differently. If you send red, and it looks blue + or green on the strip, modify this! It should be one of the values above + + + Example for TinyPICO: + + .. code-block:: python + + from dotstar import DotStar + from machine import Pin, SPI + + spi = SPI(sck=Pin(12), mosi=Pin(13), miso=Pin(18)) # Configure SPI - note: miso is unused + dotstar = DotStar(spi, 1) + dotstar[0] = (128, 0, 0) # Red + """ + + def __init__(self, spi, n, *, brightness=1.0, auto_write=True, + pixel_order=BGR): + self._spi = spi + self._n = n + # Supply one extra clock cycle for each two pixels in the strip. + self.end_header_size = n // 16 + if n % 16 != 0: + self.end_header_size += 1 + self._buf = bytearray(n * 4 + START_HEADER_SIZE + self.end_header_size) + self.end_header_index = len(self._buf) - self.end_header_size + self.pixel_order = pixel_order + # Four empty bytes to start. + for i in range(START_HEADER_SIZE): + self._buf[i] = 0x00 + # Mark the beginnings of each pixel. + for i in range(START_HEADER_SIZE, self.end_header_index, 4): + self._buf[i] = 0xff + # 0xff bytes at the end. + for i in range(self.end_header_index, len(self._buf)): + self._buf[i] = 0xff + self._brightness = 1.0 + # Set auto_write to False temporarily so brightness setter does _not_ + # call show() while in __init__. + self.auto_write = False + self.brightness = brightness + self.auto_write = auto_write + + def deinit(self): + """Blank out the DotStars and release the resources.""" + self.auto_write = False + for i in range(START_HEADER_SIZE, self.end_header_index): + if i % 4 != 0: + self._buf[i] = 0 + self.show() + if self._spi: + self._spi.deinit() + + def __enter__(self): + return self + + def __exit__(self, exception_type, exception_value, traceback): + self.deinit() + + def __repr__(self): + return "[" + ", ".join([str(x) for x in self]) + "]" + + def _set_item(self, index, value): + """ + value can be one of three things: + a (r,g,b) list/tuple + a (r,g,b, brightness) list/tuple + a single, longer int that contains RGB values, like 0xFFFFFF + brightness, if specified should be a float 0-1 + + Set a pixel value. You can set per-pixel brightness here, if it's not passed it + will use the max value for pixel brightness value, which is a good default. + + Important notes about the per-pixel brightness - it's accomplished by + PWMing the entire output of the LED, and that PWM is at a much + slower clock than the rest of the LEDs. This can cause problems in + Persistence of Vision Applications + """ + + offset = index * 4 + START_HEADER_SIZE + rgb = value + if isinstance(value, int): + rgb = (value >> 16, (value >> 8) & 0xff, value & 0xff) + + if len(rgb) == 4: + brightness = value[3] + # Ignore value[3] below. + else: + brightness = 1 + + # LED startframe is three "1" bits, followed by 5 brightness bits + # then 8 bits for each of R, G, and B. The order of those 3 are configurable and + # vary based on hardware + # same as math.ceil(brightness * 31) & 0b00011111 + # Idea from https://www.codeproject.com/Tips/700780/Fast-floor-ceiling-functions + brightness_byte = 32 - int(32 - brightness * 31) & 0b00011111 + self._buf[offset] = brightness_byte | LED_START + self._buf[offset + 1] = rgb[self.pixel_order[0]] + self._buf[offset + 2] = rgb[self.pixel_order[1]] + self._buf[offset + 3] = rgb[self.pixel_order[2]] + + def __setitem__(self, index, val): + if isinstance(index, slice): + start, stop, step = index.indices(self._n) + length = stop - start + if step != 0: + # same as math.ceil(length / step) + # Idea from https://fizzbuzzer.com/implement-a-ceil-function/ + length = (length + step - 1) // step + if len(val) != length: + raise ValueError("Slice and input sequence size do not match.") + for val_i, in_i in enumerate(range(start, stop, step)): + self._set_item(in_i, val[val_i]) + else: + self._set_item(index, val) + + if self.auto_write: + self.show() + + def __getitem__(self, index): + if isinstance(index, slice): + out = [] + for in_i in range(*index.indices(self._n)): + out.append( + tuple(self._buf[in_i * 4 + (3 - i) + START_HEADER_SIZE] for i in range(3))) + return out + if index < 0: + index += len(self) + if index >= self._n or index < 0: + raise IndexError + offset = index * 4 + return tuple(self._buf[offset + (3 - i) + START_HEADER_SIZE] + for i in range(3)) + + def __len__(self): + return self._n + + @property + def brightness(self): + """Overall brightness of the pixel""" + return self._brightness + + @brightness.setter + def brightness(self, brightness): + self._brightness = min(max(brightness, 0.0), 1.0) + if self.auto_write: + self.show() + + def fill(self, color): + """Colors all pixels the given ***color***.""" + auto_write = self.auto_write + self.auto_write = False + for i in range(self._n): + self[i] = color + if auto_write: + self.show() + self.auto_write = auto_write + + def show(self): + """Shows the new colors on the pixels themselves if they haven't already + been autowritten. + + The colors may or may not be showing after this function returns because + it may be done asynchronously.""" + # Create a second output buffer if we need to compute brightness + buf = self._buf + if self.brightness < 1.0: + buf = bytearray(self._buf) + # Four empty bytes to start. + for i in range(START_HEADER_SIZE): + buf[i] = 0x00 + for i in range(START_HEADER_SIZE, self.end_header_index): + buf[i] = self._buf[i] if i % 4 == 0 else int(self._buf[i] * self._brightness) + # Four 0xff bytes at the end. + for i in range(self.end_header_index, len(buf)): + buf[i] = 0xff + + if self._spi: + self._spi.write(buf) diff --git a/ports/esp32/boards/TINYPICO/modules/tinypico.py b/ports/esp32/boards/TINYPICO/modules/tinypico.py new file mode 100644 index 0000000000000..2fc379ccd4540 --- /dev/null +++ b/ports/esp32/boards/TINYPICO/modules/tinypico.py @@ -0,0 +1,113 @@ +# TinyPICO MicroPython Helper Library +# 2019 Seon Rozenblum, Matt Trentini +# +# Project home: +# https://github.com/TinyPICO +# +# 2019-Mar-12 - v0.1 - Initial implementation +# 2019-May-20 - v1.0 - Initial Release +# 2019-Oct-23 - v1.1 - Removed temp sensor code, prep for frozen modules + +# Import required libraries +from micropython import const +from machine import Pin, SPI, ADC +import machine, time, esp32 + +# TinyPICO Hardware Pin Assignments + +# Battery +BAT_VOLTAGE = const(35) +BAT_CHARGE = const(34) + +# APA102 Dotstar pins for production boards +DOTSTAR_CLK = const(12) +DOTSTAR_DATA = const(2) +DOTSTAR_PWR = const(13) + +# SPI +SPI_MOSI = const(23) +SPI_CLK = const(18) +SPI_MISO = const(19) + +#I2C +I2C_SDA = const(21) +I2C_SCL = const(22) + +#DAC +DAC1 = const(25) +DAC2 = const(26) + +# Helper functions + +# Get a *rough* estimate of the current battery voltage +# If the battery is not present, the charge IC will still report it's trying to charge at X voltage +# so it will still show a voltage. +def get_battery_voltage(): + """ + Returns the current battery voltage. If no battery is connected, returns 3.7V + This is an approximation only, but useful to detect of the charge state of the battery is getting low. + """ + adc = ADC(Pin(BAT_VOLTAGE)) # Assign the ADC pin to read + measuredvbat = adc.read() # Read the value + measuredvbat /= 4095 # divide by 4095 as we are using the default ADC voltage range of 0-1V + measuredvbat *= 3.7 # Multiply by 3.7V, our reference voltage + return measuredvbat + +# Return the current charge state of the battery - we need to read the value multiple times +# to eliminate false negatives due to the charge IC not knowing the difference between no battery +# and a full battery not charging - This is why the charge LED flashes +def get_battery_charging(): + """ + Returns the current battery charging state. + This can trigger false positives as the charge IC can't tell the difference between a full battery or no battery connected. + """ + measuredVal = 0 # start our reading at 0 + io = Pin(BAT_CHARGE, Pin.IN) # Assign the pin to read + + for y in range(0, 10): # loop through 10 times adding the read values together to ensure no false positives + measuredVal += io.value() + + return measuredVal == 0 # return True if the value is 0 + + +# Power to the on-board Dotstar is controlled by a PNP transistor, so low is ON and high is OFF +# We also need to set the Dotstar clock and data pins to be inputs to prevent power leakage when power is off +# This might be improved at a future date +# The reason we have power control for the Dotstar is that it has a quiescent current of around 1mA, so we +# need to be able to cut power to it to minimise power consumption during deep sleep or with general battery powered use +# to minimise unneeded battery drain +def set_dotstar_power(state): + """Set the power for the on-board Dostar to allow no current draw when not needed.""" + # Set the power pin to the inverse of state + if state: + Pin(DOTSTAR_PWR, Pin.OUT, None) # Break the PULL_HOLD on the pin + Pin(DOTSTAR_PWR).value(False) # Set the pin to LOW to enable the Transistor + else: + Pin(13, Pin.IN, Pin.PULL_HOLD) # Set PULL_HOLD on the pin to allow the 3V3 pull-up to work + + Pin(DOTSTAR_CLK, Pin.OUT if state else Pin.IN) # If power is on, set CLK to be output, otherwise input + Pin(DOTSTAR_DATA, Pin.OUT if state else Pin.IN) # If power is on, set DATA to be output, otherwise input + + # A small delay to let the IO change state + time.sleep(.035) + +# Dotstar rainbow colour wheel +def dotstar_color_wheel(wheel_pos): + """Color wheel to allow for cycling through the rainbow of RGB colors.""" + wheel_pos = wheel_pos % 255 + + if wheel_pos < 85: + return 255 - wheel_pos * 3, 0, wheel_pos * 3 + elif wheel_pos < 170: + wheel_pos -= 85 + return 0, wheel_pos * 3, 255 - wheel_pos * 3 + else: + wheel_pos -= 170 + return wheel_pos * 3, 255 - wheel_pos * 3, 0 + +# Go into deep sleep but shut down the APA first to save power +# Use this if you want lowest deep sleep current +def go_deepsleep(t): + """Deep sleep helper that also powers down the on-board Dotstar.""" + set_dotstar_power(False) + machine.deepsleep(t) diff --git a/ports/esp32/boards/TINYPICO/mpconfigboard.mk b/ports/esp32/boards/TINYPICO/mpconfigboard.mk index 485b3f16564d0..5c96ec45a79e6 100644 --- a/ports/esp32/boards/TINYPICO/mpconfigboard.mk +++ b/ports/esp32/boards/TINYPICO/mpconfigboard.mk @@ -4,3 +4,5 @@ SDKCONFIG += boards/sdkconfig.base SDKCONFIG += boards/sdkconfig.240mhz SDKCONFIG += boards/sdkconfig.spiram SDKCONFIG += boards/TINYPICO/sdkconfig.board + +FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py From 8af139e8a4a01c2eea034df4e3eb96488ec3231b Mon Sep 17 00:00:00 2001 From: roland van straten Date: Mon, 9 Dec 2019 14:53:48 +0100 Subject: [PATCH 0798/1299] stm32/boards/NUCLEO_F767ZI: Add pins and config for using an SD card. The Nucleo board does not have an SD card slot but does have the requisite pins next to each other and labelled, so provide the configuration for convenience. --- ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h | 6 ++++++ ports/stm32/boards/NUCLEO_F767ZI/pins.csv | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h index 1ee73c303b380..b144ce466837a 100644 --- a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h @@ -12,6 +12,7 @@ #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_HW_ENABLE_USB (1) +#define MICROPY_HW_ENABLE_SDCARD (1) #define MICROPY_BOARD_EARLY_INIT NUCLEO_F767ZI_board_early_init void NUCLEO_F767ZI_board_early_init(void); @@ -71,6 +72,11 @@ void NUCLEO_F767ZI_board_early_init(void); #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) #define MICROPY_HW_USB_OTG_ID_PIN (pin_A10) +// SD card detect switch (actual pin may need to be changed for a particular use) +#define MICROPY_HW_SDCARD_DETECT_PIN (pin_G2) +#define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) +#define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) + // Ethernet via RMII #define MICROPY_HW_ETH_MDC (pin_C1) #define MICROPY_HW_ETH_MDIO (pin_A2) diff --git a/ports/stm32/boards/NUCLEO_F767ZI/pins.csv b/ports/stm32/boards/NUCLEO_F767ZI/pins.csv index d84f8e9d1957b..ccd90d4475682 100644 --- a/ports/stm32/boards/NUCLEO_F767ZI/pins.csv +++ b/ports/stm32/boards/NUCLEO_F767ZI/pins.csv @@ -46,7 +46,13 @@ AUDIO_SCL,PH7 EXT_SDA,PB9 EXT_SCL,PB8 EXT_RST,PG3 -SD_SW,PC13 +SD_D0,PC8 +SD_D1,PC9 +SD_D2,PC10 +SD_D3,PC11 +SD_CMD,PD2 +SD_CK,PC12 +SD_SW,PG2 LCD_BL_CTRL,PK3 LCD_INT,PI13 LCD_SDA,PH8 From 26a78edb49152db4ab4b22db9ccc25030a706357 Mon Sep 17 00:00:00 2001 From: roland van straten Date: Wed, 11 Dec 2019 11:43:47 +0100 Subject: [PATCH 0799/1299] stm32/boards/NUCLEO_F767ZI: Update pins, peripherals and total flash. - Removed remarks on DFU/OCD in mpconfigboard.h because deploy-stlink works fine too. - Added more UARTs, I2C, corrected SPI, CAN, etc; verified against CubeMX. - Adapted pins.csv to remove errors, add omissions, etc. according to NUCLEO-144 User Manual. - Changed linker file stm32f767.ld to reflect correct size of the Flash. - Tested with LAN and SD card. --- .../boards/NUCLEO_F767ZI/mpconfigboard.h | 29 +++--- ports/stm32/boards/NUCLEO_F767ZI/pins.csv | 98 ++++++++++++++----- ports/stm32/boards/stm32f767.ld | 2 +- 3 files changed, 92 insertions(+), 37 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h index b144ce466837a..b659223b4d94e 100644 --- a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.h @@ -1,7 +1,5 @@ -// This board is only confirmed to operate using DFU mode and openocd. -// DFU mode can be accessed by setting BOOT0 (see schematics) -// To use openocd run "OPENOCD_CONFIG=boards/openocd_stm32f7.cfg" in -// the make command. +// Note: if the board shows odd behaviour check the option bits and make sure nDBANK is +// set to make the 2MByte space continuous instead of divided into two 1MByte segments. #define MICROPY_HW_BOARD_NAME "NUCLEO-F767ZI" #define MICROPY_HW_MCU_NAME "STM32F767" @@ -31,16 +29,25 @@ void NUCLEO_F767ZI_board_early_init(void); #define MICROPY_HW_UART2_CTS (pin_D3) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) -#define MICROPY_HW_UART6_TX (pin_G14) -#define MICROPY_HW_UART6_RX (pin_G9) +#define MICROPY_HW_UART6_TX (pin_C6) +#define MICROPY_HW_UART6_RX (pin_C7) +#define MICROPY_HW_UART5_TX (pin_B6) +#define MICROPY_HW_UART5_RX (pin_B12) +#define MICROPY_HW_UART7_TX (pin_F7) +#define MICROPY_HW_UART7_RX (pin_F6) +#define MICROPY_HW_UART8_TX (pin_E1) +#define MICROPY_HW_UART8_RX (pin_E0) + #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 // I2C busses #define MICROPY_HW_I2C1_SCL (pin_B8) #define MICROPY_HW_I2C1_SDA (pin_B9) -#define MICROPY_HW_I2C3_SCL (pin_H7) -#define MICROPY_HW_I2C3_SDA (pin_H8) +#define MICROPY_HW_I2C2_SCL (pin_F1) +#define MICROPY_HW_I2C2_SDA (pin_F0) +#define MICROPY_HW_I2C4_SCL (pin_F14) +#define MICROPY_HW_I2C4_SDA (pin_F15) // SPI #define MICROPY_HW_SPI3_NSS (pin_A4) @@ -49,10 +56,8 @@ void NUCLEO_F767ZI_board_early_init(void); #define MICROPY_HW_SPI3_MOSI (pin_B5) // CAN busses -#define MICROPY_HW_CAN1_TX (pin_B9) -#define MICROPY_HW_CAN1_RX (pin_B8) -#define MICROPY_HW_CAN2_TX (pin_B13) -#define MICROPY_HW_CAN2_RX (pin_B12) +#define MICROPY_HW_CAN1_TX (pin_D1) +#define MICROPY_HW_CAN1_RX (pin_D0) // USRSW is pulled low. Pressing the button makes the input go high. #define MICROPY_HW_USRSW_PIN (pin_C13) diff --git a/ports/stm32/boards/NUCLEO_F767ZI/pins.csv b/ports/stm32/boards/NUCLEO_F767ZI/pins.csv index ccd90d4475682..e447b76b05b06 100644 --- a/ports/stm32/boards/NUCLEO_F767ZI/pins.csv +++ b/ports/stm32/boards/NUCLEO_F767ZI/pins.csv @@ -33,19 +33,58 @@ D22,PB5 D23,PB3 D24,PA4 D25,PB4 +D26,PB6 +D27,PB2 +D28,PD13 +D29,PD12 +D30,PD11 +D31,PE2 +D32,PA0 +D33,PB0 +D34,PE0 +D35,PB11 +D36,PB10 +D37,PE15 +D38,PE14 +D39,PE12 +D40,PE10 +D41,PE7 +D42,PE8 +D43,PC8 +D44,PC9 +D45,PC10 +D46,PC11 +D47,PC12 +D48,PD2 +D49,PG2 +D50,PG3 +D51,PD7 +D52,PD6 +D53,PD5 +D54,PD4 +D55,PD3 +D56,PE2 +D57,PE4 +D58,PE5 +D59,PE6 +D60,PE3 +D61,PF8 +D62,PF7 +D63,PF9 +D64,PG1 +D65,PG0 +D66,PD1 +D67,PD0 +D68,PF0 +D69,PF1 +D70,PF2 +D71,PA7 +DAC1,PA4 +DAC2,PA5 LED1,PB0 LED2,PB7 LED3,PB14 SW,PC13 -TP1,PH2 -TP2,PI8 -TP3,PH15 -AUDIO_INT,PD6 -AUDIO_SDA,PH8 -AUDIO_SCL,PH7 -EXT_SDA,PB9 -EXT_SCL,PB8 -EXT_RST,PG3 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 @@ -53,29 +92,38 @@ SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD_SW,PG2 -LCD_BL_CTRL,PK3 -LCD_INT,PI13 -LCD_SDA,PH8 -LCD_SCL,PH7 -OTG_FS_POWER,PD5 -OTG_FS_OVER_CURRENT,PD4 -OTG_HS_OVER_CURRENT,PE3 +OTG_FS_POWER,PG6 +OTG_FS_OVER_CURRENT,PG7 USB_VBUS,PA9 USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 -USB_POWER,PG6 -VCP_TX,PD8 -VCP_RX,PD9 UART2_TX,PD5 UART2_RX,PD6 UART2_RTS,PD4 UART2_CTS,PD3 -UART6_TX,PG14 -UART6_RX,PG9 -SPI_B_NSS,PA4 -SPI_B_SCK,PB3 -SPI_B_MOSI,PB5 +VCP_TX,PD8 +VCP_RX,PD9 +UART3_TX,PD8 +UART3_RX,PD9 +UART5_TX,PB6 +UART5_RX,PB12 +UART6_TX,PC6 +UART6_RX,PC7 +UART7_TX,PF7 +UART7_RX,PF6 +UART8_TX,PE1 +UART8_RX,PE0 +SPI3_NSS,PA4 +SPI3_SCK,PB3 +SPI3_MISO,PB4 +SPI3_MOSI,PB5 +I2C1_SDA,PB9 +I2C1_SCL,PB8 +I2C2_SDA,PF0 +I2C2_SCL,PF1 +I2C4_SCL,PF14 +I2C4_SDA,PF15 ETH_MDC,PC1 ETH_MDIO,PA2 ETH_RMII_REF_CLK,PA1 @@ -85,3 +133,5 @@ ETH_RMII_RXD1,PC5 ETH_RMII_TX_EN,PG11 ETH_RMII_TXD0,PG13 ETH_RMII_TXD1,PB13 +SWDIO,PA13 +SWDCLK,PA14 diff --git a/ports/stm32/boards/stm32f767.ld b/ports/stm32/boards/stm32f767.ld index 9410b9fa6b73e..d07f2ecbef085 100644 --- a/ports/stm32/boards/stm32f767.ld +++ b/ports/stm32/boards/stm32f767.ld @@ -5,7 +5,7 @@ /* Specify the memory areas */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 32K /* sector 0, 32K */ FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 2016K /* sectors 1-11 3x32K 1*128K 7*256K */ FLASH_FS (r) : ORIGIN = 0x08008000, LENGTH = 96K /* sectors 1, 2, 3 (32K each) */ From 43b576d88d3a9802bd38a30bb4266fed889db903 Mon Sep 17 00:00:00 2001 From: roland van straten Date: Tue, 10 Dec 2019 21:52:30 +0100 Subject: [PATCH 0800/1299] stm32/boards/NUCLEO_H743ZI: Add extra pins and peripheral definitions. - Corrected pin assignments and checked with CubeMX. - Added additional I2C and UARTs. - Added Ethernet interface definitions with lwIP and SSL support (but Ethernet is currently unsupported on H7 MCUs so not fully enabled). --- .../boards/NUCLEO_H743ZI/mpconfigboard.h | 26 ++++ .../boards/NUCLEO_H743ZI/mpconfigboard.mk | 5 + ports/stm32/boards/NUCLEO_H743ZI/pins.csv | 145 +++++++++++++----- 3 files changed, 135 insertions(+), 41 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h index 40ce889ab9b79..4e6b162269a8a 100644 --- a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h +++ b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.h @@ -31,8 +31,21 @@ void NUCLEO_H743ZI_board_early_init(void); #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4 // UART config +#define MICROPY_HW_UART2_TX (pin_D5) +#define MICROPY_HW_UART2_RX (pin_D6) +#define MICROPY_HW_UART2_RTS (pin_D4) +#define MICROPY_HW_UART2_CTS (pin_D3) #define MICROPY_HW_UART3_TX (pin_D8) #define MICROPY_HW_UART3_RX (pin_D9) +#define MICROPY_HW_UART5_TX (pin_B6) +#define MICROPY_HW_UART5_RX (pin_B12) +#define MICROPY_HW_UART6_TX (pin_C6) +#define MICROPY_HW_UART6_RX (pin_C7) +#define MICROPY_HW_UART7_TX (pin_F7) +#define MICROPY_HW_UART7_RX (pin_F6) +#define MICROPY_HW_UART8_TX (pin_E1) +#define MICROPY_HW_UART8_RX (pin_E0) + #define MICROPY_HW_UART_REPL PYB_UART_3 #define MICROPY_HW_UART_REPL_BAUD 115200 @@ -41,6 +54,8 @@ void NUCLEO_H743ZI_board_early_init(void); #define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_F1) #define MICROPY_HW_I2C2_SDA (pin_F0) +#define MICROPY_HW_I2C4_SCL (pin_F14) +#define MICROPY_HW_I2C4_SDA (pin_F15) // SPI #define MICROPY_HW_SPI3_NSS (pin_A4) @@ -75,3 +90,14 @@ void NUCLEO_H743ZI_board_early_init(void); #define MICROPY_HW_SDCARD_DETECT_PIN (pin_G2) #define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP) #define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET) + +// Ethernet via RMII (MDC define disabled for now until eth.c supports H7) +//#define MICROPY_HW_ETH_MDC (pin_C1) +#define MICROPY_HW_ETH_MDIO (pin_A2) +#define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1) +#define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7) +#define MICROPY_HW_ETH_RMII_RXD0 (pin_C4) +#define MICROPY_HW_ETH_RMII_RXD1 (pin_C5) +#define MICROPY_HW_ETH_RMII_TX_EN (pin_G11) +#define MICROPY_HW_ETH_RMII_TXD0 (pin_G13) +#define MICROPY_HW_ETH_RMII_TXD1 (pin_B13) diff --git a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk index 1d232e0803f19..ce8f83e57d52b 100644 --- a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk @@ -16,3 +16,8 @@ LD_FILES = boards/stm32h743.ld boards/common_ifs.ld TEXT0_ADDR = 0x08000000 TEXT1_ADDR = 0x08040000 endif + +# MicroPython settings +MICROPY_PY_LWIP = 1 +MICROPY_PY_USSL = 1 +MICROPY_SSL_MBEDTLS = 1 diff --git a/ports/stm32/boards/NUCLEO_H743ZI/pins.csv b/ports/stm32/boards/NUCLEO_H743ZI/pins.csv index daa36691b7b96..d3647ca42a3ea 100644 --- a/ports/stm32/boards/NUCLEO_H743ZI/pins.csv +++ b/ports/stm32/boards/NUCLEO_H743ZI/pins.csv @@ -1,46 +1,97 @@ -A0,PA0 -A1,PF10 -A2,PF9 -A3,PF8 -A4,PF7 -A5,PF6 -D0,PC7 -D1,PC6 -D2,PG6 -D3,PB4 -D4,PG7 -D5,PA8 -D6,PH6 -D7,PI3 -D8,PI2 -D9,PA15 -D10,PI0 -D11,PB15 -D12,PB14 -D13,PI1 +A0,PA3 +A1,PC0 +A2,PC3 +A3,PB1 +A4,PC2 +A5,PF10 +A6,PF4 +A7,PF5 +A8,PF6 +D0,PB7 +D1,PB6 +D2,PG14 +D3,PE13 +D4,PE14 +D5,PE11 +D6,PE9 +D7,PG12 +D8,PF3 +D9,PD15 +D10,PD14 +D11,PB5 +D12,PA6 +D13,PA7 D14,PB9 D15,PB8 +D16,PC6 +D17,PB15 +D18,PB13 +D19,PB12 +D20,PA15 +D21,PC7 D22,PB5 D23,PB3 -D67,PD0 +D24,PA4 +D25,PB4 +D26,PG6 +D27,PB2 +D28,PD13 +D29,PD12 +D30,PD11 +D31,PE2 +D32,PA0 +D33,PB0 +D34,PE0 +D35,PB11 +D36,PB10 +D37,PE15 +D38,PE6 +D39,PE12 +D40,PE10 +D41,PE7 +D42,PE8 +D43,PC8 +D44,PC9 +D45,PC10 +D46,PC11 +D47,PC12 +D48,PD2 +D49,PG2 +D50,PG3 +D51,PD7 +D52,PD6 +D53,PD5 +D54,PD4 +D55,PD3 +D56,PE2 +D57,PE4 +D58,PE5 +D59,PE6 +D60,PE3 +D61,PF8 +D62,PF7 +D63,PF9 +D64,PG1 +D65,PG0 D66,PD1 +D67,PD0 +D68,PF0 +D69,PF1 +D70,PF2 +D71,PE9 +D72,PB2 DAC1,PA4 DAC2,PA5 LED1,PB0 LED2,PB7 LED3,PB14 SW,PC13 -TP1,PH2 -TP2,PI8 -TP3,PH15 -AUDIO_INT,PD6 -AUDIO_SDA,PH8 -AUDIO_SCL,PH7 I2C1_SDA,PB9 I2C1_SCL,PB8 I2C2_SDA,PF0 I2C2_SCL,PF1 -EXT_RST,PG3 +I2C4_SCL,PF14 +I2C4_SDA,PF15 SD_D0,PC8 SD_D1,PC9 SD_D2,PC10 @@ -48,20 +99,32 @@ SD_D3,PC11 SD_CMD,PD2 SD_CK,PC12 SD_SW,PG2 -LCD_BL_CTRL,PK3 -LCD_INT,PI13 -LCD_SDA,PH8 -LCD_SCL,PH7 -OTG_FS_POWER,PD5 -OTG_FS_OVER_CURRENT,PD4 -OTG_HS_OVER_CURRENT,PE3 -USB_VBUS,PJ12 -USB_ID,PA8 +OTG_FS_POWER,PG6 +OTG_FS_OVER_CURRENT,PG7 +USB_VBUS,PA9 +USB_ID,PA10 USB_DM,PA11 USB_DP,PA12 -UART1_TX,PA9 -UART1_RX,PA10 -UART5_TX,PC12 -UART5_RX,PD2 +UART2_TX,PD5 +UART2_RX,PD6 +UART2_RTS,PD4 +UART2_CTS,PD3 UART3_TX,PD8 UART3_RX,PD9 +UART5_TX,PB6 +UART5_RX,PB12 +UART6_TX,PC6 +UART6_RX,PC7 +UART7_TX,PF7 +UART7_RX,PF6 +UART8_TX,PE1 +UART8_RX,PE0 +ETH_MDC,PC1 +ETH_MDIO,PA2 +ETH_RMII_REF_CLK,PA1 +ETH_RMII_CRS_DV,PA7 +ETH_RMII_RXD0,PC4 +ETH_RMII_RXD1,PC5 +ETH_RMII_TX_EN,PG11 +ETH_RMII_TXD0,PG13 +ETH_RMII_TXD1,PB13 From b3b9b11596b5b4c9a3c45185fd839fa3db63fa12 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 11 Dec 2019 14:56:33 +1100 Subject: [PATCH 0801/1299] tools/pyboard.py: Support executing .mpy files directly. This patch allows executing .mpy files (including native ones) directly on a target, eg a board over a serial connection. So there's no need to copy the file to its filesystem to test it. For example: $ mpy-cross foo.py $ pyboard.py foo.mpy --- tools/pyboard.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tools/pyboard.py b/tools/pyboard.py index c32fb002ca6ec..2a255e91c0753 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -484,6 +484,33 @@ def fname_cp_dest(src, dest): pyb.close() sys.exit(1) +_injected_import_hook_code = """\ +import uos, uio +class _FS: + class File(uio.IOBase): + def __init__(self): + self.off = 0 + def ioctl(self, request, arg): + return 0 + def readinto(self, buf): + buf[:] = memoryview(_injected_buf)[self.off:self.off + len(buf)] + self.off += len(buf) + return len(buf) + mount = umount = chdir = lambda *args: None + def stat(self, path): + if path == '_injected.mpy': + return tuple(0 for _ in range(10)) + else: + raise OSError(-2) # ENOENT + def open(self, path, mode): + return self.File() +uos.mount(_FS(), '/_') +uos.chdir('/_') +from _injected import * +uos.umount('/_') +del _injected_buf, _FS +""" + def main(): import argparse cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.') @@ -544,6 +571,9 @@ def execbuffer(buf): for filename in args.files: with open(filename, 'rb') as f: pyfile = f.read() + if filename.endswith('.mpy') and pyfile[0] == ord('M'): + pyb.exec_('_injected_buf=' + repr(pyfile)) + pyfile = _injected_import_hook_code execbuffer(pyfile) # exiting raw-REPL just drops to friendly-REPL mode From a3df152fef9b2e022bd4b1233df12c261cb9f1a8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Dec 2019 22:40:22 +1100 Subject: [PATCH 0802/1299] examples/natmod: Add very simple features0 example to compute factorial. --- examples/natmod/features0/Makefile | 14 ++++++++++ examples/natmod/features0/features0.c | 40 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 examples/natmod/features0/Makefile create mode 100644 examples/natmod/features0/features0.c diff --git a/examples/natmod/features0/Makefile b/examples/natmod/features0/Makefile new file mode 100644 index 0000000000000..57490df90abe7 --- /dev/null +++ b/examples/natmod/features0/Makefile @@ -0,0 +1,14 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module +MOD = features0 + +# Source files (.c or .py) +SRC = features0.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +# Include to get the rules for compiling and linking the module +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features0/features0.c b/examples/natmod/features0/features0.c new file mode 100644 index 0000000000000..1b1867a3bc935 --- /dev/null +++ b/examples/natmod/features0/features0.c @@ -0,0 +1,40 @@ +/* This example demonstrates the following features in a native module: + - defining a simple function exposed to Python + - defining a local, helper C function + - getting and creating integer objects +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// Helper function to compute factorial +STATIC mp_int_t factorial_helper(mp_int_t x) { + if (x == 0) { + return 1; + } + return x * factorial_helper(x - 1); +} + +// This is the function which will be called from Python, as factorial(x) +STATIC mp_obj_t factorial(mp_obj_t x_obj) { + // Extract the integer from the MicroPython input object + mp_int_t x = mp_obj_get_int(x_obj); + // Calculate the factorial + mp_int_t result = factorial_helper(x); + // Convert the result to a MicroPython integer object and return it + return mp_obj_new_int(result); +} +// Define a Python reference to the function above +STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial); + +// This is the entry point and is called when the module is imported +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Make the function available in the module's namespace + mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} From e58c7ce3d64fe17a58e75616a4992921f6bc5738 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Dec 2019 23:03:38 +1100 Subject: [PATCH 0803/1299] docs/reference: Add documentation describing use of .mpy files. Including information about .mpy versioning and how to debug failed imports of .mpy files. --- docs/reference/index.rst | 1 + docs/reference/mpyfiles.rst | 178 ++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 docs/reference/mpyfiles.rst diff --git a/docs/reference/index.rst b/docs/reference/index.rst index 1eaaa85c856f1..ed50bf0bf47cd 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -21,6 +21,7 @@ implementation and the best practices to use them. glossary.rst repl.rst + mpyfiles.rst isr_rules.rst speed_python.rst constrained.rst diff --git a/docs/reference/mpyfiles.rst b/docs/reference/mpyfiles.rst new file mode 100644 index 0000000000000..4791784ac3a2e --- /dev/null +++ b/docs/reference/mpyfiles.rst @@ -0,0 +1,178 @@ +.. _mpy_files: + +MicroPython .mpy files +====================== + +MicroPython defines the concept of an .mpy file which is a binary container +file format that holds precompiled code, and which can be imported like a +normal .py module. The file ``foo.mpy`` can be imported via ``import foo``, +as long as ``foo.mpy`` can be found in the usual way by the import machinery. +Usually, each directory listed in ``sys.path`` is searched in order. When +searching a particular directory ``foo.py`` is looked for first and if that +is not found then ``foo.mpy`` is looked for, then the search continues in the +next directory if neither is found. As such, ``foo.py`` will take precedence +over ``foo.mpy``. + +These .mpy files can contain bytecode which is usually generated from Python +source files (.py files) via the ``mpy-cross`` program. For some architectures +an .mpy file can also contain native machine code, which can be generated in +a variety of ways, most notably from C source code. + +Versioning and compatibility of .mpy files +------------------------------------------ + +A given .mpy file may or may not be compatible with a given MicroPython system. +Compatibility is based on the following: + +* Version of the .mpy file: the version of the file must match the version + supported by the system loading it. + +* Bytecode features used in the .mpy file: there are two bytecode features + which must match between the file and the system: unicode support and + inline caching of map lookups in the bytecode. + +* Small integer bits: the .mpy file will require a minimum number of bits in + a small integer and the system loading it must support at least this many + bits. + +* Qstr compression window size: the .mpy file will require a minimum window + size for qstr decompression and the system loading it must have a window + greater or equal to this size. + +* Native architecture: if the .mpy file contains native machine code then + it will specify the architecture of that machine code and the system + loading it must support execution of that architecture's code. + +If a MicroPython system supports importing .mpy files then the +``sys.implementation.mpy`` field will exist and return an integer which +encodes the version (lower 8 bits), features and native architecture. + +Trying to import an .mpy file that fails one of the first four tests will +raise ``ValueError('incompatible .mpy file')``. Trying to import an .mpy +file that fails the native architecture test (if it contains native machine +code) will raise ``ValueError('incompatible .mpy arch')``. + +If importing an .mpy file fails then try the following: + +* Determine the .mpy version and flags supported by your MicroPython system + by executing:: + + import sys + sys_mpy = sys.implementation.mpy + arch = [None, 'x86', 'x64', + 'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp', + 'xtensa', 'xtensawin'][sys_mpy >> 10] + print('mpy version:', sys_mpy & 0xff) + print('mpy flags:', end='') + if arch: + print(' -march=' + arch, end='') + if sys_mpy & 0x100: + print(' -mcache-lookup-bc', end='') + if not sys_mpy & 0x200: + print(' -mno-unicode', end='') + print() + +* Check the validity of the .mpy file by inspecting the first two bytes of + the file. The first byte should be an uppercase 'M' and the second byte + will be the version number, which should match the system version from above. + If it doesn't match then rebuild the .mpy file. + +* Check if the system .mpy version matches the version emitted by ``mpy-cross`` + that was used to build the .mpy file, found by ``mpy-cross --version``. + If it doesn't match then recompile ``mpy-cross`` from the Git repository + checked out at the tag (or hash) reported by ``mpy-cross --version``. + +* Make sure you are using the correct ``mpy-cross`` flags, found by the code + above, or by inspecting the ``MPY_CROSS_FLAGS`` Makefile variable for the + port that you are using. + +The following table shows the correspondence between MicroPython release +and .mpy version. + +=================== ============ +MicroPython release .mpy version +=================== ============ +v1.12 and up 5 +v1.11 4 +v1.9.3 - v1.10 3 +v1.9 - v1.9.2 2 +v1.5.1 - v1.8.7 0 +=================== ============ + +For completeness, the next table shows the Git commit of the main +MicroPython repository at which the .mpy version was changed. + +=================== ======================================== +.mpy version change Git commit +=================== ======================================== +4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517 +3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e +2 to 3 ff93fd4f50321c6190e1659b19e64fef3045a484 +1 to 2 dd11af209d226b7d18d5148b239662e30ed60bad +0 to 1 6a11048af1d01c78bdacddadd1b72dc7ba7c6478 +initial version 0 d8c834c95d506db979ec871417de90b7951edc30 +=================== ======================================== + +Binary encoding of .mpy files +----------------------------- + +MicroPython .mpy files are a binary container format with code objects +stored internally in a nested hierarchy. To keep files small while still +providing a large range of possible values it uses the concept of a +variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8 +encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set +if one or more bytes follow. The bits of the unsigned integer are stored +in the vuint in LSB form. + +The top-level of an .mpy file consists of two parts: + +* The header. + +* The raw-code for the outer scope of the module. + This outer scope is executed when the .mpy file is imported. + +The header +~~~~~~~~~~ + +The .mpy header is: + +====== ================================ +size field +====== ================================ +byte value 0x4d (ASCII 'M') +byte .mpy version number +byte feature flags +byte number of bits in a small int +vuint size of qstr window +====== ================================ + +Raw code elements +~~~~~~~~~~~~~~~~~ + +A raw-code element contains code, either bytecode or native machine code. Its +contents are: + +====== ================================ +size field +====== ================================ +vuint type and size +... code (bytecode or machine code) +vuint number of constant objects +vuint number of sub-raw-code elements +... constant objects +... sub-raw-code elements +====== ================================ + +The first vuint in a raw-code element encodes the type of code stored in this +element (the two least-significant bits), and the decompressed length of the code +(the amount of RAM to allocate for it). + +Following the vuint comes the code itself. In the case of bytecode it also contains +compressed qstr values. + +Following the code comes a vuint counting the number of constant objects, and +another vuint counting the number of sub-raw-code elements. + +The constant objects are then stored next. + +Finally any sub-raw-code elements are stored, recursively. From 8449e41818f26c1e3a970d7181bb82ae2d3e2278 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Dec 2019 23:04:01 +1100 Subject: [PATCH 0804/1299] docs/develop: Add documentation on how to build native .mpy modules. --- docs/develop/cmodules.rst | 6 ++ docs/develop/index.rst | 1 + docs/develop/natmod.rst | 202 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 docs/develop/natmod.rst diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index ba43c3dc93cb1..a4c473347860b 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -1,3 +1,5 @@ +.. _cmodules: + MicroPython external C modules ============================== @@ -17,6 +19,10 @@ more sense to keep this external to the main MicroPython repository. This chapter describes how to compile such external modules into the MicroPython executable or firmware image. +An alternative approach is to use :ref:`natmod` which allows writing custom C +code that is placed in a .mpy file, which can be imported dynamically in to +a running MicroPython system without the need to recompile the main firmware. + Structure of an external C module --------------------------------- diff --git a/docs/develop/index.rst b/docs/develop/index.rst index fff3e43d74824..f1fd0692ec9e1 100644 --- a/docs/develop/index.rst +++ b/docs/develop/index.rst @@ -11,3 +11,4 @@ See the `getting started guide cmodules.rst qstr.rst + natmod.rst diff --git a/docs/develop/natmod.rst b/docs/develop/natmod.rst new file mode 100644 index 0000000000000..1ce2381640dd8 --- /dev/null +++ b/docs/develop/natmod.rst @@ -0,0 +1,202 @@ +.. _natmod: + +Native machine code in .mpy files +================================= + +This section describes how to build and work with .mpy files that contain native +machine code from a language other than Python. This allows you to +write code in a language like C, compile and link it into a .mpy file, and then +import this file like a normal Python module. This can be used for implementing +functionality which is performance critical, or for including an existing +library written in another language. + +One of the main advantages of using native .mpy files is that native machine code +can be imported by a script dynamically, without the need to rebuild the main +MicroPython firmware. This is in contrast to :ref:`cmodules` which also allows +defining custom modules in C but they must be compiled into the main firmware image. + +The focus here is on using C to build native modules, but in principle any +language which can be compiled to stand-alone machine code can be put into a +.mpy file. + +A native .mpy module is built using the ``mpy_ld.py`` tool, which is found in the +``tools/`` directory of the project. This tool takes a set of object files +(.o files) and links them together to create a native .mpy files. + +Supported features and limitations +---------------------------------- + +A .mpy file can contain MicroPython bytecode and/or native machine code. If it +contains native machine code then the .mpy file has a specific architecture +associated with it. Current supported architectures are (these are the valid +options for the ``ARCH`` variable, see below): + +* ``x86`` (32 bit) +* ``x64`` (64 bit x86) +* ``armv7m`` (ARM Thumb 2, eg Cortex-M3) +* ``armv7emsp`` (ARM Thumb 2, single precision float, eg Cortex-M4F, Cortex-M7) +* ``armv7emdp`` (ARM Thumb 2, double precision float, eg Cortex-M7) +* ``xtensa`` (non-windowed, eg ESP8266) +* ``xtensawin`` (windowed with window size 8, eg ESP32) + +When compiling and linking the native .mpy file the architecture must be chosen +and the corresponding file can only be imported on that architecture. For more +details about .mpy files see :ref:`mpy_files`. + +Native code must be compiled as position independent code (PIC) and use a global +offset table (GOT), although the details of this varies from architecture to +architecture. When importing .mpy files with native code the import machinery +is able to do some basic relocation of the native code. This includes +relocating text, rodata and BSS sections. + +Supported features of the linker and dynamic loader are: + +* executable code (text) +* read-only data (rodata), including strings and constant data (arrays, structs, etc) +* zeroed data (BSS) +* pointers in text to text, rodata and BSS +* pointers in rodata to text, rodata and BSS + +The known limitations are: + +* data sections are not supported; workaround: use BSS data and initialise the + data values explicitly + +* static BSS variables are not supported; workaround: use global BSS variables + +So, if your C code has writable data, make sure the data is defined globally, +without an initialiser, and only written to within functions. + +Defining a native module +------------------------ + +A native .mpy module is defined by a set of files that are used to build the .mpy. +The filesystem layout consists of two main parts, the source files and the Makefile: + +* In the simplest case only a single C source file is required, which contains all + the code that will be compiled into the .mpy module. This C source code must + include the ``py/dynruntime.h`` file to access the MicroPython dynamic API, and + must at least define a function called ``mpy_init``. This function will be the + entry point of the module, called when the module is imported. + + The module can be split into multiple C source files if desired. Parts of the + module can also be implemented in Python. All source files should be listed in + the Makefile, by adding them to the ``SRC`` variable (see below). This includes + both C source files as well as any Python files which will be included in the + resulting .mpy file. + +* The ``Makefile`` contains the build configuration for the module and list the + source files used to build the .mpy module. It should define ``MPY_DIR`` as the + location of the MicroPython repository (to find header files, the relevant Makefile + fragment, and the ``mpy_ld.py`` tool), ``MOD`` as the name of the module, ``SRC`` + as the list of source files, optionally specify the machine architecture via ``ARCH``, + and then include ``py/dynruntime.mk``. + +Minimal example +--------------- + +This section provides a fully working example of a simple module named ``factorial``. +This module provides a single function ``factorial.factorial(x)`` which computes the +factorial of the input and returns the result. + +Directory layout:: + + factorial/ + ├── factorial.c + └── Makefile + +The file ``factorial.c`` contains: + +.. code-block:: c + + // Include the header file to get access to the MicroPython API + #include "py/dynruntime.h" + + // Helper function to compute factorial + STATIC mp_int_t factorial_helper(mp_int_t x) { + if (x == 0) { + return 1; + } + return x * factorial_helper(x - 1); + } + + // This is the function which will be called from Python, as factorial(x) + STATIC mp_obj_t factorial(mp_obj_t x_obj) { + // Extract the integer from the MicroPython input object + mp_int_t x = mp_obj_get_int(x_obj); + // Calculate the factorial + mp_int_t result = factorial_helper(x); + // Convert the result to a MicroPython integer object and return it + return mp_obj_new_int(result); + } + // Define a Python reference to the function above + STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial); + + // This is the entry point and is called when the module is imported + mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Make the function available in the module's namespace + mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT + } + +The file ``Makefile`` contains: + +.. code-block:: make + + # Location of top-level MicroPython directory + MPY_DIR = ../../.. + + # Name of module + MOD = features0 + + # Source files (.c or .py) + SRC = features0.c + + # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) + ARCH = x64 + + # Include to get the rules for compiling and linking the module + include $(MPY_DIR)/py/dynruntime.mk + +Compiling the module +-------------------- + +Be sure to select the correct ``ARCH`` for the target you are going to run on. +Then build with:: + + $ make + +Without modifying the Makefile you can specify the target architecture via:: + + $ make ARCH=armv7m + +Module usage in MicroPython +--------------------------- + +Once the module is built there should be a file called ``factorial.mpy``. Copy +this so it is accessible on the filesystem of your MicroPython system and can be +found in the import path. The module con now be accessed in Python just like any +other module, for example:: + + import factorial + print(factorial.factorial(10)) + # should display 3628800 + +Further examples +---------------- + +See ``examples/natmod/`` for further examples which show many of the available +features of native .mpy modules. Such features include: + +* using multiple C source files +* including Python code alongside C code +* rodata and BSS data +* memory allocation +* use of floating point +* exception handling +* including external C libraries From 3078a4b2e233a7c224cd4f337b8fadf5bf53257f Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Tue, 17 Dec 2019 19:43:26 +0200 Subject: [PATCH 0805/1299] stm32/timer: Add missing TIM 1/15/16/17 IRQ handlers for H7 MCUs. --- ports/stm32/stm32_it.c | 28 ++++++++++++++++++++++++++++ ports/stm32/timer.c | 4 +++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index e12cf4bf29920..e77642b8ea3ea 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -609,6 +609,14 @@ void TIM1_UP_TIM16_IRQHandler(void) { } #endif +#if defined(STM32H7) +void TIM1_UP_IRQHandler(void) { + IRQ_ENTER(TIM1_UP_IRQn); + timer_irq_handler(1); + IRQ_EXIT(TIM1_UP_IRQn); +} +#endif + void TIM1_TRG_COM_TIM11_IRQHandler(void) { IRQ_ENTER(TIM1_TRG_COM_TIM11_IRQn); timer_irq_handler(11); @@ -705,6 +713,26 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void) { } #endif +#if defined(STM32H7) +void TIM15_IRQHandler(void) { + IRQ_ENTER(TIM15_IRQn); + timer_irq_handler(15); + IRQ_EXIT(TIM15_IRQn); +} + +void TIM16_IRQHandler(void) { + IRQ_ENTER(TIM16_IRQn); + timer_irq_handler(16); + IRQ_EXIT(TIM16_IRQn); +} + +void TIM17_IRQHandler(void) { + IRQ_ENTER(TIM17_IRQn); + timer_irq_handler(17); + IRQ_EXIT(TIM17_IRQn); +} +#endif + // UART/USART IRQ handlers void USART1_IRQHandler(void) { IRQ_ENTER(USART1_IRQn); diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 834ebd9c85ce0..2e8f3e05ba6cd 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -759,6 +759,8 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(1, TIM1_BRK_UP_TRG_COM_IRQn), #elif defined(STM32F4) || defined(STM32F7) TIM_ENTRY(1, TIM1_UP_TIM10_IRQn), + #elif defined(STM32H7) + TIM_ENTRY(1, TIM1_UP_IRQn), #elif defined(STM32L4) TIM_ENTRY(1, TIM1_UP_TIM16_IRQn), #endif @@ -780,7 +782,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { TIM_ENTRY(7, TIM7_IRQn), #endif #if defined(TIM8) - #if defined(STM32F4) || defined(STM32F7) + #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) TIM_ENTRY(8, TIM8_UP_TIM13_IRQn), #elif defined(STM32L4) TIM_ENTRY(8, TIM8_UP_IRQn), From 1605c7e5840cf44a11a8e38150be8bb7ce6645d5 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 18 Dec 2019 12:42:34 -0600 Subject: [PATCH 0806/1299] Revert "lib/tinytest: Clean up test reporting in the presence of std..." This reverts commit f4ed2dfa942339dc1f174e8a83ff0d41073f1972. This lets tinytest work as it was originally designed. An alternate solution for the reverted commit will be implemented in a future commit. --- lib/tinytest/tinytest.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/tinytest/tinytest.c b/lib/tinytest/tinytest.c index 01772f3f8ef6e..1ef957d31bdb4 100644 --- a/lib/tinytest/tinytest.c +++ b/lib/tinytest/tinytest.c @@ -234,9 +234,8 @@ testcase_run_one(const struct testgroup_t *group, return SKIP; } - printf("# starting %s%s\n", group->prefix, testcase->name); if (opt_verbosity>0 && !opt_forked) { - //printf("%s%s: ", group->prefix, testcase->name); + printf("%s%s: ", group->prefix, testcase->name); } else { if (opt_verbosity==0) printf("."); cur_test_prefix = group->prefix; @@ -253,7 +252,6 @@ testcase_run_one(const struct testgroup_t *group, outcome = testcase_run_bare_(testcase); } - printf("%s%s: ", group->prefix, testcase->name); if (outcome == OK) { ++n_ok; if (opt_verbosity>0 && !opt_forked) @@ -265,8 +263,7 @@ testcase_run_one(const struct testgroup_t *group, } else { ++n_bad; if (!opt_forked) - //printf("\n [%s FAILED]\n", testcase->name); - puts("FAILED"); + printf("\n [%s FAILED]\n", testcase->name); } if (opt_forked) { From fd0ba7be0775fe804bc6c20f538d722705b8ea4a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 18 Dec 2019 12:59:48 -0600 Subject: [PATCH 0807/1299] tools/tinytest-codegen.py: Add extra newline and result message. This is an alternative to f4ed2df that adds a newline so that the output of the test starts on a new line and the result of the test is prefixed with "result: " to distinguish it from the test output. Suggested-by: @dpgeorge --- tools/tinytest-codegen.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index 7580522ee671f..424f70a9fbd01 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -33,8 +33,10 @@ def script_to_map(test_file): "void {name}(void* data) {{\n" " static const char pystr[] = {script};\n" " static const char exp[] = {output};\n" + ' printf("\\n");\n' " upytest_set_expected_output(exp, sizeof(exp) - 1);\n" " upytest_execute_test(pystr);\n" + ' printf("result: ");\n' "}}" ) From 882533ad9221d4a69c5523b8d04c08970d6c1988 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 18 Dec 2019 12:26:55 -0600 Subject: [PATCH 0808/1299] qemu-arm/Makefile: Allow overriding CROSS_COMPILE from another makefile. --- ports/qemu-arm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 4f12173c3fbe8..cb7dcb02160b2 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -31,7 +31,7 @@ LDSCRIPT = mps2.ld SRC_BOARD_O = lib/utils/gchelper_m3.o endif -CROSS_COMPILE = arm-none-eabi- +CROSS_COMPILE ?= arm-none-eabi- INC += -I. INC += -I$(TOP) From 0e0e6132fd90453eafabb71f355012cd82cf05b4 Mon Sep 17 00:00:00 2001 From: Matt Trentini Date: Mon, 23 Sep 2019 13:50:58 +1000 Subject: [PATCH 0809/1299] esp32/esp32_rmt: Add initial support for RMT peripheral. This is an ESP32-specific peripheral so lives in the esp32 module. --- ports/esp32/Makefile | 1 + ports/esp32/esp32_rmt.c | 237 ++++++++++++++++++++++++++++++++++++++++ ports/esp32/modesp32.c | 1 + ports/esp32/modesp32.h | 1 + 4 files changed, 240 insertions(+) create mode 100644 ports/esp32/esp32_rmt.c diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index e3b14495d5fb5..ecaa3e62acd3b 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -323,6 +323,7 @@ SRC_C = \ modsocket.c \ modesp.c \ esp32_partition.c \ + esp32_rmt.c \ esp32_ulp.c \ modesp32.c \ espneopixel.c \ diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c new file mode 100644 index 0000000000000..1356456bc5dd7 --- /dev/null +++ b/ports/esp32/esp32_rmt.c @@ -0,0 +1,237 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 "Matt Trentini" + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "modmachine.h" +#include "mphalport.h" +#include "driver/rmt.h" + +// This exposes the ESP32's RMT module to MicroPython. RMT is provided by the Espressif ESP-IDF: +// +// https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html +// +// With some examples provided: +// +// https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/RMT +// +// RMT allows accurate (down to 12.5ns resolution) transmit - and receive - of pulse signals. +// Originally designed to generate infrared remote control signals, the module is very +// flexible and quite easy-to-use. +// +// This current MicroPython implementation lacks some major features, notably receive pulses +// and carrier output. + +// Forward declaration +extern const mp_obj_type_t esp32_rmt_type; + +typedef struct _esp32_rmt_obj_t { + mp_obj_base_t base; + uint8_t channel_id; + gpio_num_t pin; + uint8_t clock_div; + mp_uint_t num_items; + rmt_item32_t* items; +} esp32_rmt_obj_t; + +// Defined in machine_time.c; simply added the error message +// Fixme: Should use this updated error hadline more widely in the ESP32 port. +// At least update the method in machine_time.c. +STATIC esp_err_t check_esp_err(esp_err_t code) { + if (code) { + mp_raise_msg(&mp_type_OSError, esp_err_to_name(code)); + } + + return code; +} + +STATIC mp_obj_t esp32_rmt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_clock_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, // 100ns resolution + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_uint_t channel_id = args[0].u_int; + gpio_num_t pin_id = machine_pin_get_id(args[1].u_obj); + mp_uint_t clock_div = args[2].u_int; + + if (clock_div < 1 || clock_div > 255) { + mp_raise_ValueError("clock_div must be between 1 and 255"); + } + + esp32_rmt_obj_t *self = m_new_obj_with_finaliser(esp32_rmt_obj_t); + self->base.type = &esp32_rmt_type; + self->channel_id = channel_id; + self->pin = pin_id; + self->clock_div = clock_div; + + rmt_config_t config; + config.rmt_mode = RMT_MODE_TX; + config.channel = (rmt_channel_t) self->channel_id; + config.gpio_num = self->pin; + config.mem_block_num = 1; + config.tx_config.loop_en = 0; + + config.tx_config.carrier_en = 0; + config.tx_config.idle_output_en = 1; + config.tx_config.idle_level = 0; + config.tx_config.carrier_duty_percent = 0; + config.tx_config.carrier_freq_hz = 0; + config.tx_config.carrier_level = 1; + + config.clk_div = self->clock_div; + + check_esp_err(rmt_config(&config)); + check_esp_err(rmt_driver_install(config.channel, 0, 0)); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC void esp32_rmt_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->pin != -1) { + mp_printf(print, "RMT(channel=%u, pin=%u, source_freq=%u, clock_div=%u)", + self->channel_id, self->pin, APB_CLK_FREQ, self->clock_div); + } else { + mp_printf(print, "RMT()"); + } +} + +STATIC mp_obj_t esp32_rmt_deinit(mp_obj_t self_in) { + // fixme: check for valid channel. Return exception if error occurs. + esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->pin != -1) { // Check if channel has already been deinitialised. + rmt_driver_uninstall(self->channel_id); + self->pin = -1; // -1 to indicate RMT is unused + m_free(self->items); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_deinit_obj, esp32_rmt_deinit); + +// Return the source frequency. +// Currently only the APB clock (80MHz) can be used but it is possible other +// clock sources will added in the future. +STATIC mp_obj_t esp32_rmt_source_freq(mp_obj_t self_in) { + return mp_obj_new_int(APB_CLK_FREQ); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_source_freq_obj, esp32_rmt_source_freq); + +// Return the clock divider. +STATIC mp_obj_t esp32_rmt_clock_div(mp_obj_t self_in) { + esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(self->clock_div); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_clock_div_obj, esp32_rmt_clock_div); + +// Query whether the channel has finished sending pulses. Takes an optional +// timeout (in ticks of the 80MHz clock), returning true if the pulse stream has +// completed or false if they are still transmitting (or timeout is reached). +STATIC mp_obj_t esp32_rmt_wait_done(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_self, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(args[0].u_obj); + + esp_err_t err = rmt_wait_tx_done(self->channel_id, args[1].u_int); + return err == ESP_OK ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_rmt_wait_done_obj, 1, esp32_rmt_wait_done); + +STATIC mp_obj_t esp32_rmt_loop(mp_obj_t self_in, mp_obj_t loop) { + esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_esp_err(rmt_set_tx_loop_mode(self->channel_id, mp_obj_get_int(loop))); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_rmt_loop_obj, esp32_rmt_loop); + +STATIC mp_obj_t esp32_rmt_write_pulses(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_self, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_pulses, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + esp32_rmt_obj_t *self = MP_OBJ_TO_PTR(args[0].u_obj); + mp_obj_t pulses = args[1].u_obj; + mp_uint_t start = args[2].u_int; + + if (start < 0 || start > 1) { + mp_raise_ValueError("start must be 0 or 1"); + } + + size_t pulses_length = 0; + mp_obj_t* pulses_ptr = NULL; + mp_obj_get_array(pulses, &pulses_length, &pulses_ptr); + + mp_uint_t num_items = (pulses_length / 2) + (pulses_length % 2); + if (num_items > self->num_items) { + self->items = (rmt_item32_t*)m_realloc(self->items, num_items * sizeof(rmt_item32_t *)); + self->num_items = num_items; + } + + for (mp_uint_t item_index = 0; item_index < num_items; item_index++) { + mp_uint_t pulse_index = item_index * 2; + self->items[item_index].duration0 = mp_obj_get_int(pulses_ptr[pulse_index++]); + self->items[item_index].level0 = start++; // Note that start _could_ wrap. + if (pulse_index < pulses_length) { + self->items[item_index].duration1 = mp_obj_get_int(pulses_ptr[pulse_index]); + self->items[item_index].level1 = start++; + } + } + check_esp_err(rmt_write_items(self->channel_id, self->items, num_items, false /* non-blocking */)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_rmt_write_pulses_obj, 2, esp32_rmt_write_pulses); + +STATIC const mp_rom_map_elem_t esp32_rmt_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&esp32_rmt_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_rmt_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_source_freq), MP_ROM_PTR(&esp32_rmt_source_freq_obj) }, + { MP_ROM_QSTR(MP_QSTR_clock_div), MP_ROM_PTR(&esp32_rmt_clock_div_obj) }, + { MP_ROM_QSTR(MP_QSTR_wait_done), MP_ROM_PTR(&esp32_rmt_wait_done_obj) }, + { MP_ROM_QSTR(MP_QSTR_loop), MP_ROM_PTR(&esp32_rmt_loop_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_pulses), MP_ROM_PTR(&esp32_rmt_write_pulses_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(esp32_rmt_locals_dict, esp32_rmt_locals_dict_table); + +const mp_obj_type_t esp32_rmt_type = { + { &mp_type_type }, + .name = MP_QSTR_RMT, + .print = esp32_rmt_print, + .make_new = esp32_rmt_make_new, + .locals_dict = (mp_obj_dict_t*)&esp32_rmt_locals_dict, +}; diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c index ddc030e3fb6ae..77617113fc021 100644 --- a/ports/esp32/modesp32.c +++ b/ports/esp32/modesp32.c @@ -155,6 +155,7 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_hall_sensor), MP_ROM_PTR(&esp32_hall_sensor_obj) }, { MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) }, + { MP_ROM_QSTR(MP_QSTR_RMT), MP_ROM_PTR(&esp32_rmt_type) }, { MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) }, { MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_PTR(&mp_const_false_obj) }, diff --git a/ports/esp32/modesp32.h b/ports/esp32/modesp32.h index 26eec8ae69cea..f04bdba676a1b 100644 --- a/ports/esp32/modesp32.h +++ b/ports/esp32/modesp32.h @@ -27,6 +27,7 @@ #define RTC_IS_VALID_EXT_PIN(pin_id) ((1ll << (pin_id)) & RTC_VALID_EXT_PINS) extern const mp_obj_type_t esp32_partition_type; +extern const mp_obj_type_t esp32_rmt_type; extern const mp_obj_type_t esp32_ulp_type; #endif // MICROPY_INCLUDED_ESP32_MODESP32_H From 7f235cbee924305e2d8a8aa86876770af66d7d82 Mon Sep 17 00:00:00 2001 From: Matt Trentini Date: Sun, 29 Sep 2019 23:36:22 +1000 Subject: [PATCH 0810/1299] docs/esp32: Add quickref and full docs for esp32.RMT class. --- docs/esp32/general.rst | 1 + docs/esp32/quickref.rst | 14 +++++++ docs/library/esp32.rst | 87 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/docs/esp32/general.rst b/docs/esp32/general.rst index 51918d4e183ea..8137c042d9214 100644 --- a/docs/esp32/general.rst +++ b/docs/esp32/general.rst @@ -52,6 +52,7 @@ For your convenience, some of technical specifications are provided below: * I2S: 2 * ADC: 12-bit SAR ADC up to 18 channels * DAC: 2 8-bit DACs +* RMT: 8 channels allowing accurate pulse transmit/receive * Programming: using BootROM bootloader from UART - due to external FlashROM and always-available BootROM bootloader, the ESP32 is not brickable diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index ef9b0a2e8c4aa..cfe31664e74ea 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -365,6 +365,20 @@ Notes: p1 = Pin(4, Pin.OUT, None) +RMT +--- + +The RMT is ESP32-specific and allows generation of accurate digital pulses with +12.5ns resolution. See :ref:`esp32.RMT ` for details. Usage is:: + + import esp32 + from machine import Pin + + r = esp32.RMT(0, pin=Pin(18), clock_div=8) + r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) + # The channel resolution is 100ns (1/(source_freq/clock_div)). + r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns + OneWire driver -------------- diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 68379624e69b5..467af0ff0f251 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -1,3 +1,5 @@ +.. currentmodule:: esp32 + :mod:`esp32` --- functionality specific to the ESP32 ==================================================== @@ -86,6 +88,91 @@ Constants Used in `Partition.find` to specify the partition type. + +.. _esp32.RMT: + +RMT +--- + +The RMT (Remote Control) module, specific to the ESP32, was originally designed +to send and receive infrared remote control signals. However, due to a flexible +design and very accurate (as low as 12.5ns) pulse generation, it can also be +used to transmit or receive many other types of digital signals:: + + import esp32 + from machine import Pin + + r = esp32.RMT(0, pin=Pin(18), clock_div=8) + r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8) + # The channel resolution is 100ns (1/(source_freq/clock_div)). + r.write_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns + +The input to the RMT module is an 80MHz clock (in the future it may be able to +configure the input clock but, for now, it's fixed). ``clock_div`` *divides* +the clock input which determines the resolution of the RMT channel. The +numbers specificed in ``write_pulses`` are multiplied by the resolution to +define the pulses. + +``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by +multiplying the resolution by a 15-bit (0-32,768) number. There are eight +channels (0-7) and each can have a different clock divider. + +So, in the example above, the 80MHz clock is divided by 8. Thus the +resolution is (1/(80Mhz/8)) 100ns. Since the ``start`` level is 0 and toggles +with each number, the bitstream is ``0101`` with durations of [100ns, 2000ns, +100ns, 4000ns]. + +For more details see Espressif's `ESP-IDF RMT documentation. +`_. + +.. Warning:: + The current MicroPython RMT implementation lacks some features, most notably + receiving pulses and carrier transmit. RMT should be considered a + *beta feature* and the interface may change in the future. + + +.. class:: RMT(channel, \*, pin=None, clock_div=8) + + This class provides access to one of the eight RMT channels. *channel* is + required and identifies which RMT channel (0-7) will be configured. *pin*, + also required, configures which Pin is bound to the RMT channel. *clock_div* + is an 8-bit clock divider that divides the source clock (80MHz) to the RMT + channel allowing the resolution to be specified. + +.. method:: RMT.source_freq() + + Returns the source clock frequency. Currently the source clock is not + configurable so this will always return 80MHz. + +.. method:: RMT.clock_div() + + Return the clock divider. Note that the channel resolution is + ``1 / (source_freq / clock_div)``. + +.. method:: RMT.wait_done(timeout=0) + + Returns True if `RMT.write_pulses` has completed. + + If *timeout* (defined in ticks of ``source_freq / clock_div``) is specified + the method will wait for *timeout* or until `RMT.write_pulses` is complete, + returning ``False`` if the channel continues to transmit. + +.. Warning:: + Avoid using ``wait_done()`` if looping is enabled. + +.. method:: RMT.loop(enable_loop) + + Configure looping on the channel, allowing a stream of pulses to be + indefinitely repeated. *enable_loop* is bool, set to True to enable looping. + +.. method:: RMT.write_pulses(pulses, start) + + Begin sending *pulses*, a list or tuple defining the stream of pulses. The + length of each pulse is defined by a number to be multiplied by the channel + resolution ``(1 / (source_freq / clock_div))``. *start* defines whether the + stream starts at 0 or 1. + + The Ultra-Low-Power co-processor -------------------------------- From 7ce1e0b1dc466e48606164aad223c81c93a9cea2 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 21 Oct 2019 15:55:18 +1100 Subject: [PATCH 0811/1299] extmod/webrepl: Move webrepl scripts to common place and use manifest. Move webrepl support code from ports/esp8266/modules into extmod/webrepl (to be alongside extmod/modwebrepl.c), and use frozen manifests to include it in the build on esp8266 and esp32. A small modification is made to webrepl.py to make it work on non-ESP ports, i.e. don't call dupterm_notify if not available. --- extmod/webrepl/manifest.py | 1 + {ports/esp8266/modules => extmod/webrepl}/webrepl.py | 5 +++-- {ports/esp8266/modules => extmod/webrepl}/webrepl_setup.py | 0 .../esp8266/modules => extmod/webrepl}/websocket_helper.py | 0 ports/esp32/boards/manifest.py | 2 +- ports/esp8266/boards/manifest.py | 1 + 6 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 extmod/webrepl/manifest.py rename {ports/esp8266/modules => extmod/webrepl}/webrepl.py (92%) rename {ports/esp8266/modules => extmod/webrepl}/webrepl_setup.py (100%) rename {ports/esp8266/modules => extmod/webrepl}/websocket_helper.py (100%) diff --git a/extmod/webrepl/manifest.py b/extmod/webrepl/manifest.py new file mode 100644 index 0000000000000..0f2b440058801 --- /dev/null +++ b/extmod/webrepl/manifest.py @@ -0,0 +1 @@ +freeze('.', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) diff --git a/ports/esp8266/modules/webrepl.py b/extmod/webrepl/webrepl.py similarity index 92% rename from ports/esp8266/modules/webrepl.py rename to extmod/webrepl/webrepl.py index bbf8bdb320efe..24c63299d50b8 100644 --- a/ports/esp8266/modules/webrepl.py +++ b/extmod/webrepl/webrepl.py @@ -43,8 +43,9 @@ def accept_conn(listen_sock): ws = uwebsocket.websocket(cl, True) ws = _webrepl._webrepl(ws) cl.setblocking(False) - # notify REPL on socket incoming data - cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify) + # notify REPL on socket incoming data (ESP32/ESP8266-only) + if hasattr(uos, 'dupterm_notify'): + cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify) uos.dupterm(ws) diff --git a/ports/esp8266/modules/webrepl_setup.py b/extmod/webrepl/webrepl_setup.py similarity index 100% rename from ports/esp8266/modules/webrepl_setup.py rename to extmod/webrepl/webrepl_setup.py diff --git a/ports/esp8266/modules/websocket_helper.py b/extmod/webrepl/websocket_helper.py similarity index 100% rename from ports/esp8266/modules/websocket_helper.py rename to extmod/webrepl/websocket_helper.py diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py index 2b07639ee9090..bab2b614ba3a2 100644 --- a/ports/esp32/boards/manifest.py +++ b/ports/esp32/boards/manifest.py @@ -1,6 +1,6 @@ freeze('$(PORT_DIR)/modules') freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) freeze('$(MPY_DIR)/ports/esp8266/modules', 'ntptime.py') -freeze('$(MPY_DIR)/ports/esp8266/modules', ('webrepl.py', 'webrepl_setup.py', 'websocket_helper.py',)) freeze('$(MPY_DIR)/drivers/dht', 'dht.py') freeze('$(MPY_DIR)/drivers/onewire') +include('$(MPY_DIR)/extmod/webrepl/manifest.py') diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py index 779e840880064..b6df53fc64634 100644 --- a/ports/esp8266/boards/manifest.py +++ b/ports/esp8266/boards/manifest.py @@ -2,3 +2,4 @@ freeze('$(MPY_DIR)/tools', ('upip.py', 'upip_utarfile.py')) freeze('$(MPY_DIR)/drivers/dht', 'dht.py') freeze('$(MPY_DIR)/drivers/onewire') +include('$(MPY_DIR)/extmod/webrepl/manifest.py') From 7ac326c4240776b20cd80956d5e1f6c005c4dc5b Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 20 Dec 2019 13:20:20 +1100 Subject: [PATCH 0812/1299] stm32/boards/PYBD: Include webrepl helper scripts in frozen manifest. --- ports/stm32/boards/PYBD_SF2/manifest.py | 2 ++ ports/stm32/boards/PYBD_SF2/mpconfigboard.mk | 3 +++ ports/stm32/boards/PYBD_SF3/mpconfigboard.mk | 3 +++ ports/stm32/boards/PYBD_SF6/mpconfigboard.mk | 3 +++ 4 files changed, 11 insertions(+) create mode 100644 ports/stm32/boards/PYBD_SF2/manifest.py diff --git a/ports/stm32/boards/PYBD_SF2/manifest.py b/ports/stm32/boards/PYBD_SF2/manifest.py new file mode 100644 index 0000000000000..48cc2ce9347fd --- /dev/null +++ b/ports/stm32/boards/PYBD_SF2/manifest.py @@ -0,0 +1,2 @@ +include('$(PORT_DIR)/boards/manifest.py') +include('$(MPY_DIR)/extmod/webrepl/manifest.py') diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk index 9c0121f3137b6..69407345bd13a 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.mk @@ -17,3 +17,6 @@ MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 MICROPY_VFS_LFS2 = 1 + +# PYBD-specific frozen modules +FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py diff --git a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk index 7bef5651dd57b..f6d6e955b616b 100644 --- a/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF3/mpconfigboard.mk @@ -16,3 +16,6 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 + +# PYBD-specific frozen modules +FROZEN_MANIFEST = boards/PYBD_SF2/manifest.py diff --git a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk index f85d9c9973284..e33d62d86a931 100644 --- a/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk +++ b/ports/stm32/boards/PYBD_SF6/mpconfigboard.mk @@ -13,3 +13,6 @@ MICROPY_PY_LWIP = 1 MICROPY_PY_NETWORK_CYW43 = 1 MICROPY_PY_USSL = 1 MICROPY_SSL_MBEDTLS = 1 + +# PYBD-specific frozen modules +FROZEN_MANIFEST = boards/PYBD_SF2/manifest.py From 95473980ef350174095887451d80690657f3315a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 20 Dec 2019 14:57:06 +1100 Subject: [PATCH 0813/1299] py/vm: Fix comment to refer to MP_BC_RAISE_OBJ instead of RAISE_VARARGS. --- py/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/vm.c b/py/vm.c index 7c702f3863cfc..11dbffaffcab5 100644 --- a/py/vm.c +++ b/py/vm.c @@ -269,7 +269,7 @@ FRAME_SETUP(); MICROPY_VM_HOOK_INIT // If we have exception to inject, now that we finish setting up - // execution context, raise it. This works as if RAISE_VARARGS + // execution context, raise it. This works as if MP_BC_RAISE_OBJ // bytecode was executed. // Injecting exc into yield from generator is a special case, // handled by MP_BC_YIELD_FROM itself From 073c5f3a40abd4bd7691f5468f0106ed4379ebfb Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 20 Dec 2019 14:57:44 +1100 Subject: [PATCH 0814/1299] py/profile: Fix debug opcode decoding of MP_BC_RAISE_xxx opcodes. --- py/profile.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/py/profile.c b/py/profile.c index f16d4d701ee1f..72726cdf52647 100644 --- a/py/profile.c +++ b/py/profile.c @@ -875,10 +875,16 @@ STATIC const byte *mp_prof_opcode_decode(const byte *ip, const mp_uint_t *const_ instruction->qstr_opname = MP_QSTR_RETURN_VALUE; break; - case MP_BC_RAISE_VARARGS: - unum = *ip++; - instruction->qstr_opname = MP_QSTR_RAISE_VARARGS; - instruction->arg = unum; + case MP_BC_RAISE_LAST: + instruction->qstr_opname = MP_QSTR_RAISE_LAST; + break; + + case MP_BC_RAISE_OBJ: + instruction->qstr_opname = MP_QSTR_RAISE_OBJ; + break; + + case MP_BC_RAISE_FROM: + instruction->qstr_opname = MP_QSTR_RAISE_FROM; break; case MP_BC_YIELD_VALUE: From 39bc430e44173430776e7336c9e622d52affe59a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 20 Dec 2019 16:42:38 +1100 Subject: [PATCH 0815/1299] tests/pyb: Adjust UART and Timer tests to work on PYBD_SF6. --- tests/pyb/timer.py | 2 +- tests/pyb/uart.py | 2 +- tests/pyb/uart.py.exp | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/pyb/timer.py b/tests/pyb/timer.py index e83550abd8d9a..0e24ff4ad4165 100644 --- a/tests/pyb/timer.py +++ b/tests/pyb/timer.py @@ -16,4 +16,4 @@ tim = Timer(2, freq=100) print(tim.freq()) tim.freq(0.001) -print(tim.freq()) +print('{:.3f}'.format(tim.freq())) diff --git a/tests/pyb/uart.py b/tests/pyb/uart.py index 82a66dd2e05de..9dcb1f75cd33a 100644 --- a/tests/pyb/uart.py +++ b/tests/pyb/uart.py @@ -1,7 +1,7 @@ from pyb import UART # test we can correctly create by id -for bus in (-1, 0, 1, 2, 5, 6, 7): +for bus in (-1, 0, 1, 2, 5, 6): try: UART(bus, 9600) print("UART", bus) diff --git a/tests/pyb/uart.py.exp b/tests/pyb/uart.py.exp index 1a4cbd9381e84..70e4ab8509fcd 100644 --- a/tests/pyb/uart.py.exp +++ b/tests/pyb/uart.py.exp @@ -4,7 +4,6 @@ UART 1 UART 2 ValueError 5 UART 6 -ValueError 7 UART(1, baudrate=9600, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=3, rxbuf=64) UART(1, baudrate=2400, bits=8, parity=None, stop=1, flow=0, timeout=0, timeout_char=7, rxbuf=64) 0 From 1f371947309c5ea6023b6d9065415697cbc75578 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 20 Dec 2019 16:58:17 +1100 Subject: [PATCH 0816/1299] all: Bump version to 1.12. --- docs/conf.py | 2 +- py/mpconfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index dbd1d0c562946..36f99cd2c441b 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -74,7 +74,7 @@ # # We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags" # breakdown, so use the same version identifier for both to avoid confusion. -version = release = '1.11' +version = release = '1.12' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/py/mpconfig.h b/py/mpconfig.h index e46da3e83c721..1e786f753b6d6 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -28,7 +28,7 @@ // Current version of MicroPython #define MICROPY_VERSION_MAJOR 1 -#define MICROPY_VERSION_MINOR 11 +#define MICROPY_VERSION_MINOR 12 #define MICROPY_VERSION_MICRO 0 // Combined version as a 32-bit number for convenience From 035180ca015d01934094adea52affbf867e4cdc6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 20 Dec 2019 23:34:46 +1100 Subject: [PATCH 0817/1299] py: Remove commented-out debug printf's from emitbc and objlist. Any debugging prints should use a macro like DEBUG_printf. --- py/emitbc.c | 4 ---- py/objlist.c | 2 -- 2 files changed, 6 deletions(-) diff --git a/py/emitbc.c b/py/emitbc.c index 34f6362ff000b..ee4a7d5f8ad40 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -110,7 +110,6 @@ STATIC void emit_write_uint(emit_t *emit, emit_allocator_t allocator, mp_uint_t // all functions must go through this one to emit code info STATIC byte *emit_get_cur_to_write_code_info(emit_t *emit, int num_bytes_to_write) { - //printf("emit %d\n", num_bytes_to_write); if (emit->pass < MP_PASS_EMIT) { emit->code_info_offset += num_bytes_to_write; return emit->dummy_data; @@ -140,7 +139,6 @@ STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) { #if MICROPY_ENABLE_SOURCE_LINE STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) { assert(bytes_to_skip > 0 || lines_to_skip > 0); - //printf(" %d %d\n", bytes_to_skip, lines_to_skip); while (bytes_to_skip > 0 || lines_to_skip > 0) { mp_uint_t b, l; if (lines_to_skip <= 6 || bytes_to_skip > 0xf) { @@ -169,7 +167,6 @@ STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_sk // all functions must go through this one to emit byte code STATIC byte *emit_get_cur_to_write_bytecode(emit_t *emit, int num_bytes_to_write) { - //printf("emit %d\n", num_bytes_to_write); if (emit->pass < MP_PASS_EMIT) { emit->bytecode_offset += num_bytes_to_write; return emit->dummy_data; @@ -470,7 +467,6 @@ void mp_emit_bc_adjust_stack_size(emit_t *emit, mp_int_t delta) { } void mp_emit_bc_set_source_line(emit_t *emit, mp_uint_t source_line) { - //printf("source: line %d -> %d offset %d -> %d\n", emit->last_source_line, source_line, emit->last_source_line_offset, emit->bytecode_offset); #if MICROPY_ENABLE_SOURCE_LINE if (MP_STATE_VM(mp_optimise_value) >= 3) { // If we compile with -O3, don't store line numbers. diff --git a/py/objlist.c b/py/objlist.c index ec9d57fc7bdab..29a1d8b1a455e 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -162,7 +162,6 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } mp_int_t len_adj = slice.start - slice.stop; - //printf("Len adj: %d\n", len_adj); assert(len_adj <= 0); mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, sizeof(*self->items)); // Clear "freed" elements at the end of list @@ -201,7 +200,6 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_raise_NotImplementedError(NULL); } mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start); - //printf("Len adj: %d\n", len_adj); if (len_adj > 0) { if (self->len + len_adj > self->alloc) { // TODO: Might optimize memory copies here by checking if block can From 5e431188db5e23a6fef5e6b3892e17354f1aac59 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 20 Dec 2019 23:36:17 +1100 Subject: [PATCH 0818/1299] py/obj.h: Remove comments about additional mp_buffer_info_t entries. These entries are unlikely to be needed, so remove them to clean up the struct definition. --- py/obj.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/py/obj.h b/py/obj.h index 5b54892ce8090..7c6815a3c2f9d 100644 --- a/py/obj.h +++ b/py/obj.h @@ -435,18 +435,9 @@ typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_b // Buffer protocol typedef struct _mp_buffer_info_t { - // if we'd bother to support various versions of structure - // (with different number of fields), we can distinguish - // them with ver = sizeof(struct). Cons: overkill for *micro*? - //int ver; // ? - void *buf; // can be NULL if len == 0 size_t len; // in bytes int typecode; // as per binary.h - - // Rationale: to load arbitrary-sized sprites directly to LCD - // Cons: a bit adhoc usecase - // int stride; } mp_buffer_info_t; #define MP_BUFFER_READ (1) #define MP_BUFFER_WRITE (2) From 90f286465b670feb94c3ce8857c81bad3df18b96 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 7 Nov 2019 22:15:33 +1100 Subject: [PATCH 0819/1299] stm32/mbedtls: Resize mbedtls output buffer from 16 down to 4 kiB. To reduce the size of the SSL context on the heap. See issue #5303. --- ports/stm32/mbedtls/mbedtls_config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/stm32/mbedtls/mbedtls_config.h b/ports/stm32/mbedtls/mbedtls_config.h index 4820140766f4d..338c8b354146b 100644 --- a/ports/stm32/mbedtls/mbedtls_config.h +++ b/ports/stm32/mbedtls/mbedtls_config.h @@ -54,6 +54,11 @@ #define MBEDTLS_SSL_PROTO_TLS1_2 #define MBEDTLS_SSL_SERVER_NAME_INDICATION +// Use a smaller output buffer to reduce size of SSL context +#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384) +#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096) + // Enable mbedtls modules #define MBEDTLS_AES_C #define MBEDTLS_ASN1_PARSE_C From 07ccb5588c4abcffa28f25907e699d1727d38bae Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 9 Dec 2019 18:31:35 +0200 Subject: [PATCH 0820/1299] py/objobject: Add object.__setattr__ function. Allows assigning attributes on class instances that implement their own __setattr__. Both object.__setattr__ and super(A, b).__setattr__ will work with this commit. --- py/objobject.c | 22 +++++++++++++++++++++- py/runtime.c | 4 +++- tests/basics/class_delattr_setattr.py | 26 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/py/objobject.c b/py/objobject.c index 45228347e965a..ae8436bc889bf 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -50,7 +50,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__); STATIC mp_obj_t object___new__(mp_obj_t cls) { if (!mp_obj_is_type(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) { - mp_raise_TypeError("__new__ arg must be a user-type"); + mp_raise_TypeError("arg must be user-type"); } // This executes only "__new__" part of instance creation. // TODO: This won't work well for classes with native bases. @@ -62,6 +62,23 @@ STATIC mp_obj_t object___new__(mp_obj_t cls) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj)); +#if MICROPY_PY_DELATTR_SETATTR +STATIC mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t value) { + if (!mp_obj_is_instance_type(mp_obj_get_type(MP_OBJ_TO_PTR(self_in)))) { + mp_raise_TypeError("arg must be user-type"); + } + + if (!mp_obj_is_str(attr)) { + mp_raise_TypeError(NULL); + } + + mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); + mp_map_lookup(&self->members, attr, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(object___setattr___obj, object___setattr__); +#endif + STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&object___init___obj) }, @@ -69,6 +86,9 @@ STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR___new__), MP_ROM_PTR(&object___new___obj) }, #endif + #if MICROPY_PY_DELATTR_SETATTR + { MP_ROM_QSTR(MP_QSTR___setattr__), MP_ROM_PTR(&object___setattr___obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); diff --git a/py/runtime.c b/py/runtime.c index deb82e9355096..cf4fc5d38fabe 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1038,9 +1038,11 @@ void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t || m_type == &mp_type_fun_builtin_1 || m_type == &mp_type_fun_builtin_2 || m_type == &mp_type_fun_builtin_3 - || m_type == &mp_type_fun_builtin_var)) { + || m_type == &mp_type_fun_builtin_var) + && type != &mp_type_object) { // we extracted a builtin method without a first argument, so we must // wrap this function in a type checker + // Note that object will do its own checking so shouldn't be wrapped. dest[0] = mp_obj_new_checked_fun(type, member); } else #endif diff --git a/tests/basics/class_delattr_setattr.py b/tests/basics/class_delattr_setattr.py index 190b4875b90bc..8fe1bb6fc1511 100644 --- a/tests/basics/class_delattr_setattr.py +++ b/tests/basics/class_delattr_setattr.py @@ -60,3 +60,29 @@ def __delattr__(self, attr): print(a.a) except AttributeError: print("AttributeError") + +# test object.__setattr__ +class C: + def __init__(self): + pass + + def __setattr__(self, attr, value): + print(attr, "=", value) + +c = C() +c.a = 5 +try: + print(c.a) +except AttributeError: + print("AttributeError") + +object.__setattr__(c, "a", 5) +super(C, c).__setattr__("b", 6) +print(c.a) +print(c.b) + +try: + # attribute name must be string + object.__setattr__(c, 5, 5) +except TypeError: + print("TypeError") From 42e45bd69491e56d4baa681eb34f13ca1c4bd1ba Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 10 Dec 2019 12:05:22 +0200 Subject: [PATCH 0821/1299] py/objobject: Add object.__delattr__ function. Similar to object.__setattr__. --- py/objobject.c | 18 ++++++++++++++++++ tests/basics/class_delattr_setattr.py | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/py/objobject.c b/py/objobject.c index ae8436bc889bf..fcf03905979c6 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -77,6 +77,23 @@ STATIC mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t val return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(object___setattr___obj, object___setattr__); + +STATIC mp_obj_t object___delattr__(mp_obj_t self_in, mp_obj_t attr) { + if (!mp_obj_is_instance_type(mp_obj_get_type(MP_OBJ_TO_PTR(self_in)))) { + mp_raise_TypeError("arg must be user-type"); + } + + if (!mp_obj_is_str(attr)) { + mp_raise_TypeError(NULL); + } + + mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); + if (mp_map_lookup(&self->members, attr, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == NULL) { + mp_raise_msg(&mp_type_AttributeError, "no such attribute"); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(object___delattr___obj, object___delattr__); #endif STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { @@ -88,6 +105,7 @@ STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { #endif #if MICROPY_PY_DELATTR_SETATTR { MP_ROM_QSTR(MP_QSTR___setattr__), MP_ROM_PTR(&object___setattr___obj) }, + { MP_ROM_QSTR(MP_QSTR___delattr__), MP_ROM_PTR(&object___delattr___obj) }, #endif }; diff --git a/tests/basics/class_delattr_setattr.py b/tests/basics/class_delattr_setattr.py index 8fe1bb6fc1511..3389c091abc04 100644 --- a/tests/basics/class_delattr_setattr.py +++ b/tests/basics/class_delattr_setattr.py @@ -69,6 +69,9 @@ def __init__(self): def __setattr__(self, attr, value): print(attr, "=", value) + def __delattr__(self, attr): + print("del", attr) + c = C() c.a = 5 try: @@ -86,3 +89,25 @@ def __setattr__(self, attr, value): object.__setattr__(c, 5, 5) except TypeError: print("TypeError") + + +# test object.__delattr__ +del c.a +print(c.a) + +object.__delattr__(c, "a") +try: + print(c.a) +except AttributeError: + print("AttributeError") + +super(C, c).__delattr__("b") +try: + print(c.b) +except AttributeError: + print("AttributeError") + +try: + object.__delattr__(c, "c") +except AttributeError: + print("AttributeError") From 300eb65ae75857b247fc39fbe677f6e28a7a259d Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 22 Dec 2019 22:04:45 +1100 Subject: [PATCH 0822/1299] py/nlrx86: Silence possible warnings about unused nlr argument. --- py/nlrx86.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/py/nlrx86.c b/py/nlrx86.c index 6195db63cdda1..461b459e213d9 100644 --- a/py/nlrx86.c +++ b/py/nlrx86.c @@ -56,9 +56,7 @@ __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); __attribute__((naked)) #endif unsigned int nlr_push(nlr_buf_t *nlr) { - #if !USE_NAKED (void)nlr; - #endif __asm volatile ( #if UNDO_PRELUDE From ed2be79b4930f620083256fcb5b4faf9091c9ffc Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 22 Dec 2019 22:16:32 +1100 Subject: [PATCH 0823/1299] extmod/uzlib: Explicitly cast ptr-diff-expr to unsigned. The struct member "dest" should never be less than "destStart", so their difference is never negative. Cast as such to make the comparison explicitly unsigned, ensuring the compiler produces the correct comparison instruction, and avoiding any compiler warnings. --- extmod/uzlib/tinflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/uzlib/tinflate.c b/extmod/uzlib/tinflate.c index b93bc1fa36007..045952c7553a3 100644 --- a/extmod/uzlib/tinflate.c +++ b/extmod/uzlib/tinflate.c @@ -464,7 +464,7 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) } } else { /* catch trying to point before the start of dest buffer */ - if (offs > d->dest - d->destStart) { + if (offs > (unsigned int)(d->dest - d->destStart)) { return TINF_DATA_ERROR; } d->lzOff = -offs; From b97fb683d0923d29f55cf54fc2fd5cc19186536e Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 22 Dec 2019 23:10:55 +1100 Subject: [PATCH 0824/1299] py/asmx86: Fix stack to be 16-byte aligned for entry and sub-call. --- py/asmx86.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/py/asmx86.c b/py/asmx86.c index 23160c9c20026..e4736251f87fd 100644 --- a/py/asmx86.c +++ b/py/asmx86.c @@ -403,7 +403,7 @@ void asm_x86_entry(asm_x86_t *as, int num_locals) { asm_x86_push_r32(as, ASM_X86_REG_EBX); asm_x86_push_r32(as, ASM_X86_REG_ESI); asm_x86_push_r32(as, ASM_X86_REG_EDI); - num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary + num_locals |= 3; // make it odd so stack is aligned on 16 byte boundary asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, num_locals * WORD_SIZE); as->num_locals = num_locals; } @@ -497,8 +497,14 @@ void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32) #endif void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r32) { - // TODO align stack on 16-byte boundary before the call assert(n_args <= 5); + + // Align stack on 16-byte boundary during the call + unsigned int align = ((n_args + 3) & ~3) - n_args; + if (align) { + asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, align * WORD_SIZE); + } + if (n_args > 4) { asm_x86_push_r32(as, ASM_X86_REG_ARG_5); } @@ -521,7 +527,7 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r // the caller must clean up the stack if (n_args > 0) { - asm_x86_add_i32_to_r32(as, WORD_SIZE * n_args, ASM_X86_REG_ESP); + asm_x86_add_i32_to_r32(as, (n_args + align) * WORD_SIZE, ASM_X86_REG_ESP); } } From ab75210e3338fbcc975b3c04e047ac553690f429 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 22 Dec 2019 23:13:01 +1100 Subject: [PATCH 0825/1299] py/asmx86: Remove unused 5th argument facility. In commit 71a3d6ec3bd02c5bd13334537e1bd146bb643bad mp_setup_code_state was changed from a 5-arg function to a 4-arg function, and at that point 5-arg calls in native code were no longer needed. See also commit 4f9842ad80c235188955fd83317f715033a596c0. --- py/asmx86.c | 5 +---- py/asmx86.h | 2 -- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/py/asmx86.c b/py/asmx86.c index e4736251f87fd..e69d06d8bbdd8 100644 --- a/py/asmx86.c +++ b/py/asmx86.c @@ -497,7 +497,7 @@ void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32) #endif void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r32) { - assert(n_args <= 5); + assert(n_args <= 4); // Align stack on 16-byte boundary during the call unsigned int align = ((n_args + 3) & ~3) - n_args; @@ -505,9 +505,6 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, align * WORD_SIZE); } - if (n_args > 4) { - asm_x86_push_r32(as, ASM_X86_REG_ARG_5); - } if (n_args > 3) { asm_x86_push_r32(as, ASM_X86_REG_ARG_4); } diff --git a/py/asmx86.h b/py/asmx86.h index 7ba677b2c2c3e..abcea18030be4 100644 --- a/py/asmx86.h +++ b/py/asmx86.h @@ -60,7 +60,6 @@ #define ASM_X86_REG_ARG_2 ASM_X86_REG_ECX #define ASM_X86_REG_ARG_3 ASM_X86_REG_EDX #define ASM_X86_REG_ARG_4 ASM_X86_REG_EBX -#define ASM_X86_REG_ARG_5 ASM_X86_REG_ESI // condition codes, used for jcc and setcc (despite their j-name!) #define ASM_X86_CC_JB (0x2) // below, unsigned @@ -129,7 +128,6 @@ void asm_x86_call_ind(asm_x86_t* as, size_t fun_id, mp_uint_t n_args, int temp_r #define REG_ARG_2 ASM_X86_REG_ARG_2 #define REG_ARG_3 ASM_X86_REG_ARG_3 #define REG_ARG_4 ASM_X86_REG_ARG_4 -#define REG_ARG_5 ASM_X86_REG_ARG_5 // caller-save, so can be used as temporaries #define REG_TEMP0 ASM_X86_REG_EAX From 865827ed8e423cd89309b8bdd45a13902de56c4e Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 22 Dec 2019 23:51:57 +1100 Subject: [PATCH 0826/1299] tests/run-tests: Add "--mpy-cross-flags" arg to specify mpy-cross flags. --- tests/run-tests | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/run-tests b/tests/run-tests index 77667c271153f..789a6f06c0b77 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -130,7 +130,7 @@ def run_micropython(pyb, args, test_file, is_special=False): # if running via .mpy, first compile the .py file if args.via_mpy: - subprocess.check_output([MPYCROSS, '-mcache-lookup-bc', '-o', 'mpytest.mpy', '-X', 'emit=' + args.emit, test_file]) + subprocess.check_output([MPYCROSS] + args.mpy_cross_flags.split() + ['-o', 'mpytest.mpy', '-X', 'emit=' + args.emit, test_file]) cmdlist.extend(['-m', 'mpytest']) else: cmdlist.append(test_file) @@ -566,6 +566,7 @@ the last matching regex is used: cmd_parser.add_argument('--emit', default='bytecode', help='MicroPython emitter to use (bytecode or native)') 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('--mpy-cross-flags', default='-mcache-lookup-bc', help='flags to pass to mpy-cross') cmd_parser.add_argument('--keep-path', action='store_true', help='do not clear MICROPYPATH when running tests') cmd_parser.add_argument('files', nargs='*', help='input test files') args = cmd_parser.parse_args() From 99a04b8060864bb80e6443d601342595f23ea7c4 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 12:20:15 +1100 Subject: [PATCH 0827/1299] tests/extmod: Split out VfsFat finaliser tests to separate test file. It tests independent functionality and may need to be skipped for a given port. --- tests/extmod/vfs_fat_fileio1.py | 26 ----------- tests/extmod/vfs_fat_fileio1.py.exp | 5 -- tests/extmod/vfs_fat_finaliser.py | 66 +++++++++++++++++++++++++++ tests/extmod/vfs_fat_finaliser.py.exp | 5 ++ 4 files changed, 71 insertions(+), 31 deletions(-) create mode 100644 tests/extmod/vfs_fat_finaliser.py create mode 100644 tests/extmod/vfs_fat_finaliser.py.exp diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py index d0a5e4b73ca3e..7fe040d539d37 100644 --- a/tests/extmod/vfs_fat_fileio1.py +++ b/tests/extmod/vfs_fat_fileio1.py @@ -109,29 +109,3 @@ def ioctl(self, op, arg): vfs.remove("foo_file.txt") print(list(vfs.ilistdir())) - -# Here we test that opening a file with the heap locked fails correctly. This -# is a special case because file objects use a finaliser and allocating with a -# finaliser is a different path to normal allocation. It would be better to -# test this in the core tests but there are no core objects that use finaliser. -import micropython -micropython.heap_lock() -try: - vfs.open('x', 'r') -except MemoryError: - print('MemoryError') -micropython.heap_unlock() - -# Here we test that the finaliser is actually called during a garbage collection. -import gc -N = 4 -for i in range(N): - n = 'x%d' % i - f = vfs.open(n, 'w') - f.write(n) - f = None # release f without closing - [0, 1, 2, 3] # use up Python stack so f is really gone -gc.collect() # should finalise all N files by closing them -for i in range(N): - with vfs.open('x%d' % i, 'r') as f: - print(f.read()) diff --git a/tests/extmod/vfs_fat_fileio1.py.exp b/tests/extmod/vfs_fat_fileio1.py.exp index 4eb50402c45e9..8da96e16bddd0 100644 --- a/tests/extmod/vfs_fat_fileio1.py.exp +++ b/tests/extmod/vfs_fat_fileio1.py.exp @@ -11,8 +11,3 @@ o d True [('foo_dir', 16384, 0, 0)] -MemoryError -x0 -x1 -x2 -x3 diff --git a/tests/extmod/vfs_fat_finaliser.py b/tests/extmod/vfs_fat_finaliser.py new file mode 100644 index 0000000000000..c7254c5f05fe3 --- /dev/null +++ b/tests/extmod/vfs_fat_finaliser.py @@ -0,0 +1,66 @@ +# Test VfsFat class and its finaliser + +try: + import uerrno, uos + uos.VfsFat +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +class RAMBlockDevice: + def __init__(self, blocks, sec_size=512): + self.sec_size = sec_size + self.data = bytearray(blocks * self.sec_size) + + def readblocks(self, n, buf): + for i in range(len(buf)): + buf[i] = self.data[n * self.sec_size + i] + + def writeblocks(self, n, buf): + for i in range(len(buf)): + self.data[n * self.sec_size + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # MP_BLOCKDEV_IOCTL_BLOCK_COUNT + return len(self.data) // self.sec_size + if op == 5: # MP_BLOCKDEV_IOCTL_BLOCK_SIZE + return self.sec_size + + +# Create block device, and skip test if not enough RAM +try: + bdev = RAMBlockDevice(50) +except MemoryError: + print("SKIP") + raise SystemExit + +# Format block device and create VFS object +uos.VfsFat.mkfs(bdev) +vfs = uos.VfsFat(bdev) + +# Here we test that opening a file with the heap locked fails correctly. This +# is a special case because file objects use a finaliser and allocating with a +# finaliser is a different path to normal allocation. It would be better to +# test this in the core tests but there are no core objects that use finaliser. +import micropython +micropython.heap_lock() +try: + vfs.open('x', 'r') +except MemoryError: + print('MemoryError') +micropython.heap_unlock() + +# Here we test that the finaliser is actually called during a garbage collection. +import gc +N = 4 +for i in range(N): + n = 'x%d' % i + f = vfs.open(n, 'w') + f.write(n) + f = None # release f without closing + [0, 1, 2, 3] # use up Python stack so f is really gone +gc.collect() # should finalise all N files by closing them +for i in range(N): + with vfs.open('x%d' % i, 'r') as f: + print(f.read()) diff --git a/tests/extmod/vfs_fat_finaliser.py.exp b/tests/extmod/vfs_fat_finaliser.py.exp new file mode 100644 index 0000000000000..cc51daf2a3435 --- /dev/null +++ b/tests/extmod/vfs_fat_finaliser.py.exp @@ -0,0 +1,5 @@ +MemoryError +x0 +x1 +x2 +x3 From 11b4524b39482736b84de585cf683ff5c7ba4e9b Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 22 Dec 2019 22:22:14 +1100 Subject: [PATCH 0828/1299] travis: Add new job to build and test unix coverage in 32-bit mode. --- .travis.yml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/.travis.yml b/.travis.yml index 36998300db362..8ecc9f09bbefc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -98,6 +98,44 @@ jobs: after_failure: - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) + # unix coverage 32-bit + - stage: test + env: NAME="unix coverage 32-bit build and tests" + install: + - sudo apt-get install gcc-multilib libffi-dev:i386 + - sudo apt-get install python3-pip + - sudo pip3 install setuptools + - sudo pip3 install pyelftools + - gcc --version + - python3 --version + script: + - make ${MAKEOPTS} -C mpy-cross + - make ${MAKEOPTS} -C ports/unix MICROPY_FORCE_32BIT=1 submodules + - make ${MAKEOPTS} -C ports/unix MICROPY_FORCE_32BIT=1 deplibs + - make ${MAKEOPTS} -C ports/unix MICROPY_FORCE_32BIT=1 coverage + # run the main test suite + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --emit native) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --mpy-cross-flags='-mcache-lookup-bc -march=x86' -d basics float micropython) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --emit native --mpy-cross-flags='-mcache-lookup-bc -march=x86' -d basics float micropython) + # test when input script comes from stdin + - cat tests/basics/0prelim.py | ports/unix/micropython_coverage | grep -q 'abc' + # test building native mpy modules + - make -C examples/natmod/features1 ARCH=x86 + - make -C examples/natmod/features2 ARCH=x86 + - make -C examples/natmod/btree ARCH=x86 + - make -C examples/natmod/framebuf ARCH=x86 + - make -C examples/natmod/uheapq ARCH=x86 + - make -C examples/natmod/urandom ARCH=x86 + - make -C examples/natmod/ure ARCH=x86 + - make -C examples/natmod/uzlib ARCH=x86 + # test importing .mpy generated by mpy_ld.py + - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython_coverage -m features2 + - (cd tests && ./run-natmodtests.py --arch x86 extmod/{btree*,framebuf*,uheapq*,ure*,uzlib*}.py) + after_failure: + - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) + # standard unix port - stage: test env: NAME="unix port build and tests" From aacd61893952af24049fd64f3735551ff9fc14ea Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 13 Nov 2019 21:05:34 +1100 Subject: [PATCH 0829/1299] py/runtime: Don't allocate iter buf for user-defined types. A user-defined type that defines __iter__ doesn't need any memory to be pre-allocated for its iterator (because it can't use such memory). So optimise for this case by not allocating the iter-buf. --- py/objtype.c | 8 ++++++-- py/objtype.h | 3 +++ py/runtime.c | 15 ++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/py/objtype.c b/py/objtype.c index bf089dc490db9..5d4dd7d2ffec2 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -882,7 +882,8 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons return mp_call_method_self_n_kw(member[0], member[1], n_args, n_kw, args); } -STATIC mp_obj_t instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { +// Note that iter_buf may be NULL, and needs to be allocated if needed +mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { @@ -897,6 +898,9 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) return MP_OBJ_NULL; } else if (member[0] == MP_OBJ_SENTINEL) { mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); + if (iter_buf == NULL) { + iter_buf = m_new_obj(mp_obj_iter_buf_t); + } return type->getiter(self->subobj[0], iter_buf); } else { return mp_call_method_n_kw(0, 0, member); @@ -1136,7 +1140,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) o->binary_op = instance_binary_op; o->attr = mp_obj_instance_attr; o->subscr = instance_subscr; - o->getiter = instance_getiter; + o->getiter = mp_obj_instance_getiter; //o->iternext = ; not implemented o->buffer_p.get_buffer = instance_get_buffer; diff --git a/py/objtype.h b/py/objtype.h index 3fc8c6e1b0f4b..2c613b904580b 100644 --- a/py/objtype.h +++ b/py/objtype.h @@ -51,4 +51,7 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons // this needs to be exposed for the above macros to work correctly mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); +// this needs to be exposed for mp_getiter +mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); + #endif // MICROPY_INCLUDED_PY_OBJTYPE_H diff --git a/py/runtime.c b/py/runtime.c index cf4fc5d38fabe..d5511236d4412 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -34,6 +34,7 @@ #include "py/objstr.h" #include "py/objtuple.h" #include "py/objlist.h" +#include "py/objtype.h" #include "py/objmodule.h" #include "py/objgenerator.h" #include "py/smallint.h" @@ -1165,13 +1166,13 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { return o_in; } - // if caller did not provide a buffer then allocate one on the heap - if (iter_buf == NULL) { - iter_buf = m_new_obj(mp_obj_iter_buf_t); - } - // check for native getiter (corresponds to __iter__) if (type->getiter != NULL) { + if (iter_buf == NULL && type->getiter != mp_obj_instance_getiter) { + // if caller did not provide a buffer then allocate one on the heap + // mp_obj_instance_getiter is special, it will allocate only if needed + iter_buf = m_new_obj(mp_obj_iter_buf_t); + } mp_obj_t iter = type->getiter(o_in, iter_buf); if (iter != MP_OBJ_NULL) { return iter; @@ -1183,6 +1184,10 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { mp_load_method_maybe(o_in, MP_QSTR___getitem__, dest); if (dest[0] != MP_OBJ_NULL) { // __getitem__ exists, create and return an iterator + if (iter_buf == NULL) { + // if caller did not provide a buffer then allocate one on the heap + iter_buf = m_new_obj(mp_obj_iter_buf_t); + } return mp_obj_new_getitem_iter(dest, iter_buf); } From de8c04317be76222d2fbe7c5bf50ffd5ff2fd140 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 22 Dec 2019 23:47:15 +1100 Subject: [PATCH 0830/1299] tests/micropython: Add test for yield-from while heap is locked. --- tests/micropython/heapalloc_yield_from.py | 31 +++++++++++++++++++ tests/micropython/heapalloc_yield_from.py.exp | 4 +++ 2 files changed, 35 insertions(+) create mode 100644 tests/micropython/heapalloc_yield_from.py create mode 100644 tests/micropython/heapalloc_yield_from.py.exp diff --git a/tests/micropython/heapalloc_yield_from.py b/tests/micropython/heapalloc_yield_from.py new file mode 100644 index 0000000000000..8443210f3a52e --- /dev/null +++ b/tests/micropython/heapalloc_yield_from.py @@ -0,0 +1,31 @@ +# Check that yield-from can work without heap allocation + +import micropython + +# Yielding from a function generator +def sub_gen(a): + for i in range(a): + yield i +def gen(g): + yield from g +g = gen(sub_gen(4)) +micropython.heap_lock() +print(next(g)) +print(next(g)) +micropython.heap_unlock() + +# Yielding from a user iterator +class G: + def __init__(self): + self.value = 0 + def __iter__(self): + return self + def __next__(self): + v = self.value + self.value += 1 + return v +g = gen(G()) +micropython.heap_lock() +print(next(g)) +print(next(g)) +micropython.heap_unlock() diff --git a/tests/micropython/heapalloc_yield_from.py.exp b/tests/micropython/heapalloc_yield_from.py.exp new file mode 100644 index 0000000000000..5565ed6787ffb --- /dev/null +++ b/tests/micropython/heapalloc_yield_from.py.exp @@ -0,0 +1,4 @@ +0 +1 +0 +1 From f5eec903fa961135296e2656821450979e413248 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 23 Dec 2019 00:00:53 +1100 Subject: [PATCH 0831/1299] py/objsingleton: Use mp_generic_unary_op for singleton objects. So these types more closely match NoneType, eg they can be hashed, like in CPython. --- py/objsingleton.c | 1 + tests/basics/builtin_ellipsis.py | 3 +++ tests/basics/class_notimpl.py | 3 +++ 3 files changed, 7 insertions(+) diff --git a/py/objsingleton.c b/py/objsingleton.c index 67535391ea66d..2b896305cff5b 100644 --- a/py/objsingleton.c +++ b/py/objsingleton.c @@ -47,6 +47,7 @@ const mp_obj_type_t mp_type_singleton = { { &mp_type_type }, .name = MP_QSTR_, .print = singleton_print, + .unary_op = mp_generic_unary_op, }; const mp_obj_singleton_t mp_const_ellipsis_obj = {{&mp_type_singleton}, MP_QSTR_Ellipsis}; diff --git a/tests/basics/builtin_ellipsis.py b/tests/basics/builtin_ellipsis.py index d88647a89a203..d66e86de4ab38 100644 --- a/tests/basics/builtin_ellipsis.py +++ b/tests/basics/builtin_ellipsis.py @@ -4,3 +4,6 @@ print(Ellipsis) print(... == Ellipsis) + +# Test that Ellipsis can be hashed +print(type(hash(Ellipsis))) diff --git a/tests/basics/class_notimpl.py b/tests/basics/class_notimpl.py index 308075f92f3ef..58e790716b9b7 100644 --- a/tests/basics/class_notimpl.py +++ b/tests/basics/class_notimpl.py @@ -48,3 +48,6 @@ def __neg__(self): # NotImplemented isn't handled specially in unary methods print(-c) + +# Test that NotImplemented can be hashed +print(type(hash(NotImplemented))) From 09376f0e47b3ab4a5a2a3c2c768ff913e1835cc8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Dec 2019 15:40:05 +1100 Subject: [PATCH 0832/1299] py: Introduce MP_ROM_NONE macro for ROM to refer to None object. This helps to prevent mistakes, and allows easily changing the ROM value of None if needed. --- extmod/modussl_axtls.c | 6 +++--- extmod/modussl_mbedtls.c | 6 +++--- extmod/network_cyw43.c | 10 +++++----- extmod/vfs.c | 4 ++-- extmod/vfs_fat_file.c | 4 ++-- extmod/vfs_posix_file.c | 2 +- lib/utils/mpirq.c | 2 +- ports/esp32/esp32_partition.c | 2 +- ports/esp32/network_ppp.c | 4 ++-- ports/stm32/dac.c | 2 +- ports/stm32/machine_uart.c | 2 +- ports/stm32/pin.c | 4 ++-- ports/stm32/pyb_can.c | 2 +- ports/stm32/pyb_spi.c | 2 +- ports/stm32/timer.c | 10 +++++----- ports/stm32/usb.c | 2 +- ports/unix/file.c | 6 +++--- py/obj.h | 4 ++++ py/objlist.c | 2 +- py/objproperty.c | 8 ++++---- 20 files changed, 44 insertions(+), 40 deletions(-) diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 2ea175728728f..aae1c86dcbf3d 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -246,10 +246,10 @@ STATIC const mp_obj_type_t ussl_socket_type = { STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Implement more args static const mp_arg_t allowed_args[] = { - { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index a71adc5b366da..5c41ea2d84042 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -346,10 +346,10 @@ STATIC const mp_obj_type_t ussl_socket_type = { STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Implement more args static const mp_arg_t allowed_args[] = { - { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c index 45bb6163e77c8..ad46714a3e898 100644 --- a/extmod/network_cyw43.c +++ b/extmod/network_cyw43.c @@ -166,8 +166,8 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m enum { ARG_passive, ARG_essid, ARG_bssid }; static const mp_arg_t allowed_args[] = { { MP_QSTR_passive, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_essid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_essid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -212,10 +212,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_scan_obj, 1, network_cyw43_scan) STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_essid, ARG_key, ARG_auth, ARG_bssid, ARG_channel }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_key, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_key, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; diff --git a/extmod/vfs.c b/extmod/vfs.c index 5f5fc633d8c5a..e459287d4b2d3 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -297,10 +297,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_umount_obj, mp_vfs_umount); mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_file, ARG_mode, ARG_encoding }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} }, { MP_QSTR_buffering, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; // parse args diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index fb1e582f27f9c..5867c202cd6b2 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -154,9 +154,9 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, // Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, // but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor STATIC const mp_arg_t file_open_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} }, - { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} }, }; #define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 30fde818ebc93..87c202e3b0a65 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -110,7 +110,7 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ STATIC mp_obj_t vfs_posix_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { static const mp_arg_t allowed_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} }, }; diff --git a/lib/utils/mpirq.c b/lib/utils/mpirq.c index d54c15482fd07..1bfce649d7d22 100644 --- a/lib/utils/mpirq.c +++ b/lib/utils/mpirq.c @@ -36,7 +36,7 @@ ******************************************************************************/ const mp_arg_t mp_irq_init_args[] = { - { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, }; diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index e5bd31af0ec7c..50c2173cc798e 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -109,7 +109,7 @@ STATIC mp_obj_t esp32_partition_find(size_t n_args, const mp_obj_t *pos_args, mp static const mp_arg_t allowed_args[] = { { MP_QSTR_type, MP_ARG_INT, {.u_int = ESP_PARTITION_TYPE_APP} }, { MP_QSTR_subtype, MP_ARG_INT, {.u_int = ESP_PARTITION_SUBTYPE_ANY} }, - { MP_QSTR_label, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_label, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index d868450fd0279..eb2181ed17193 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -168,8 +168,8 @@ STATIC mp_obj_t ppp_connect_py(size_t n_args, const mp_obj_t *args, mp_map_t *kw enum { ARG_authmode, ARG_username, ARG_password }; static const mp_arg_t allowed_args[] = { { MP_QSTR_authmode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PPPAUTHTYPE_NONE} }, - { MP_QSTR_username, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_password, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_username, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_password, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)]; diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c index 485829c59c5f6..9ea696248123c 100644 --- a/ports/stm32/dac.c +++ b/ports/stm32/dac.c @@ -229,7 +229,7 @@ STATIC void pyb_dac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, - { MP_QSTR_buffering, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_buffering, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; // parse args diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 5dbc133310b1f..0fe7b8bfa369c 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -221,7 +221,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const static const mp_arg_t allowed_args[] = { { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} }, { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, - { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_HWCONTROL_NONE} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c index d032d991451a1..55c4152bb07cd 100644 --- a/ports/stm32/pin.c +++ b/ports/stm32/pin.c @@ -329,7 +329,7 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, MP_ROM_PTR(&pin_debug_fun_ STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)}}, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}}, @@ -418,7 +418,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_on_obj, pin_on); STATIC mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_handler, ARG_trigger, ARG_hard }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_MODE_IT_RISING | GPIO_MODE_IT_FALLING} }, { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, }; diff --git a/ports/stm32/pyb_can.c b/ports/stm32/pyb_can.c index 0de99131f00e7..8b58da216100a 100644 --- a/ports/stm32/pyb_can.c +++ b/ports/stm32/pyb_can.c @@ -442,7 +442,7 @@ STATIC mp_obj_t pyb_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t * enum { ARG_fifo, ARG_list, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; diff --git a/ports/stm32/pyb_spi.c b/ports/stm32/pyb_spi.c index e76369973ceb4..a3cacead24bf9 100644 --- a/ports/stm32/pyb_spi.c +++ b/ports/stm32/pyb_spi.c @@ -86,7 +86,7 @@ STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, size_t n_args, co { MP_QSTR_nss, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_NSS_SOFT} }, { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_FIRSTBIT_MSB} }, { MP_QSTR_ti, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_crc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_crc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; // parse args diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 2e8f3e05ba6cd..feff93412fc30 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -594,13 +594,13 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_freq, ARG_prescaler, ARG_period, ARG_tick_hz, ARG_mode, ARG_div, ARG_callback, ARG_deadtime, ARG_brk }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIM_COUNTERMODE_UP} }, { MP_QSTR_div, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_deadtime, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_brk, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BRK_OFF} }, }; @@ -982,10 +982,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit); STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_pulse_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_pulse_width_percent, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_pulse_width_percent, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_compare, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, }; diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index f2f3d7458a117..8a4b7485bb794 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -382,7 +382,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * #endif }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_vid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = USBD_VID} }, { MP_QSTR_pid, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, diff --git a/ports/unix/file.c b/ports/unix/file.c index bb841da209cae..6c6e26b0b290c 100644 --- a/ports/unix/file.c +++ b/ports/unix/file.c @@ -148,10 +148,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno); // Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO, // but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor STATIC const mp_arg_t file_open_args[] = { - { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} }, - { MP_QSTR_buffering, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_buffering, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; #define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) diff --git a/py/obj.h b/py/obj.h index 7c6815a3c2f9d..189f37d076a7d 100644 --- a/py/obj.h +++ b/py/obj.h @@ -242,6 +242,10 @@ typedef union _mp_rom_obj_t { uint64_t u64; struct { const void *lo, *hi; } u32; // Macros to create objects that are stored in ROM. +#ifndef MP_ROM_NONE +#define MP_ROM_NONE MP_ROM_PTR(&mp_const_none_obj) +#endif + #ifndef MP_ROM_INT typedef mp_const_obj_t mp_rom_obj_t; #define MP_ROM_INT(i) MP_OBJ_NEW_SMALL_INT(i) diff --git a/py/objlist.c b/py/objlist.c index 29a1d8b1a455e..00afcd56ad97c 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -312,7 +312,7 @@ STATIC void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj // TODO Python defines sort to be stable but ours is not mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { - { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_reverse, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; diff --git a/py/objproperty.c b/py/objproperty.c index 49cb9ca1b48ba..2a7844b609cc8 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -39,10 +39,10 @@ typedef struct _mp_obj_property_t { STATIC mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { enum { ARG_fget, ARG_fset, ARG_fdel, ARG_doc }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, - { MP_QSTR_doc, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, + { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_doc, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); From d97b40bdaaeb96920541e57f6d299fb0c84a7bfd Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Dec 2019 15:42:17 +1100 Subject: [PATCH 0833/1299] py: Introduce MP_ROM_FALSE/MP_ROM_TRUE for ROM to refer to bool objects. This helps to prevent mistakes, and allows easily changing the ROM value of False/True if needed. --- extmod/vfs.c | 4 ++-- ports/esp32/modesp32.c | 4 ++-- py/obj.h | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/extmod/vfs.c b/extmod/vfs.c index e459287d4b2d3..8e3a0f18c6145 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -201,8 +201,8 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_readonly, ARG_mkfs }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_false_obj)} }, - { MP_QSTR_mkfs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_false_obj)} }, + { MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_FALSE} }, + { MP_QSTR_mkfs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_FALSE} }, }; // parse args diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c index 77617113fc021..9597e0cbd83d5 100644 --- a/ports/esp32/modesp32.c +++ b/ports/esp32/modesp32.c @@ -158,8 +158,8 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_RMT), MP_ROM_PTR(&esp32_rmt_type) }, { MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) }, - { MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_PTR(&mp_const_false_obj) }, - { MP_ROM_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), MP_ROM_PTR(&mp_const_true_obj) }, + { MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_FALSE }, + { MP_ROM_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), MP_ROM_TRUE }, }; STATIC MP_DEFINE_CONST_DICT(esp32_module_globals, esp32_module_globals_table); diff --git a/py/obj.h b/py/obj.h index 189f37d076a7d..b4ee911084ccd 100644 --- a/py/obj.h +++ b/py/obj.h @@ -246,6 +246,11 @@ typedef union _mp_rom_obj_t { uint64_t u64; struct { const void *lo, *hi; } u32; #define MP_ROM_NONE MP_ROM_PTR(&mp_const_none_obj) #endif +#ifndef MP_ROM_FALSE +#define MP_ROM_FALSE MP_ROM_PTR(&mp_const_false_obj) +#define MP_ROM_TRUE MP_ROM_PTR(&mp_const_true_obj) +#endif + #ifndef MP_ROM_INT typedef mp_const_obj_t mp_rom_obj_t; #define MP_ROM_INT(i) MP_OBJ_NEW_SMALL_INT(i) From 1f499ad2fe8bd53f4666fee0c45870fe65e2e01f Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 22:43:35 +1100 Subject: [PATCH 0834/1299] py/objobject: Fix __setattr__/__delattr__ to build in nanbox mode. --- py/objobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/objobject.c b/py/objobject.c index fcf03905979c6..71301dcc4a0d5 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -64,7 +64,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object__ #if MICROPY_PY_DELATTR_SETATTR STATIC mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t value) { - if (!mp_obj_is_instance_type(mp_obj_get_type(MP_OBJ_TO_PTR(self_in)))) { + if (!mp_obj_is_instance_type(mp_obj_get_type(self_in))) { mp_raise_TypeError("arg must be user-type"); } @@ -79,7 +79,7 @@ STATIC mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t val STATIC MP_DEFINE_CONST_FUN_OBJ_3(object___setattr___obj, object___setattr__); STATIC mp_obj_t object___delattr__(mp_obj_t self_in, mp_obj_t attr) { - if (!mp_obj_is_instance_type(mp_obj_get_type(MP_OBJ_TO_PTR(self_in)))) { + if (!mp_obj_is_instance_type(mp_obj_get_type(self_in))) { mp_raise_TypeError("arg must be user-type"); } From 6f872f81d677b91446adb2dc6ebb177f81de9bc5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 22:45:01 +1100 Subject: [PATCH 0835/1299] extmod: Fix modbluetooth and modwebrepl to build in nanbox mode. --- extmod/modbluetooth.c | 18 +++++++++--------- extmod/modwebrepl.c | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 756d3d6d1cd30..ef6bdff17dfd4 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -133,7 +133,7 @@ STATIC mp_obj_t bluetooth_uuid_make_new(const mp_obj_type_t *type, size_t n_args } } - return self; + return MP_OBJ_FROM_PTR(self); } STATIC mp_obj_t bluetooth_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { @@ -353,7 +353,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bluetooth_ble_config_obj, 1, bluetooth_ble_con STATIC mp_obj_t bluetooth_ble_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_handler, ARG_trigger }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_handler, MP_ARG_OBJ|MP_ARG_REQUIRED, {.u_obj = mp_const_none} }, + { MP_QSTR_handler, MP_ARG_OBJ|MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_BLUETOOTH_IRQ_ALL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -382,9 +382,9 @@ STATIC mp_obj_t bluetooth_ble_gap_advertise(size_t n_args, const mp_obj_t *pos_a enum { ARG_interval_us, ARG_adv_data, ARG_resp_data, ARG_connectable }; static const mp_arg_t allowed_args[] = { { MP_QSTR_interval_us, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(500000)} }, - { MP_QSTR_adv_data, MP_ARG_OBJ, {.u_obj = mp_const_none } }, - { MP_QSTR_resp_data, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none } }, - { MP_QSTR_connectable, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_true } }, + { MP_QSTR_adv_data, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_resp_data, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_connectable, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_TRUE} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -516,7 +516,7 @@ STATIC mp_obj_t bluetooth_ble_gatts_register_services(mp_obj_t self_in, mp_obj_t mp_obj_t iterable = mp_getiter(services_in, &iter_buf); mp_obj_t service_tuple_obj; - mp_obj_tuple_t *result = mp_obj_new_tuple(len, NULL); + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(len, NULL)); uint16_t **handles = m_new0(uint16_t*, len); size_t *num_handles = m_new0(size_t, len); @@ -550,7 +550,7 @@ STATIC mp_obj_t bluetooth_ble_gatts_register_services(mp_obj_t self_in, mp_obj_t // Return tuple of tuple of value handles. // TODO: Also the Generic Access service characteristics? for (i = 0; i < len; ++i) { - mp_obj_tuple_t *service_handles = mp_obj_new_tuple(num_handles[i], NULL); + mp_obj_tuple_t *service_handles = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_handles[i], NULL)); for (int j = 0; j < num_handles[i]; ++j) { service_handles->items[j] = MP_OBJ_NEW_SMALL_INT(handles[i][j]); } @@ -927,7 +927,7 @@ STATIC void schedule_ringbuf(void) { mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if (!o->irq_scheduled) { o->irq_scheduled = true; - mp_sched_schedule(MP_OBJ_FROM_PTR(MP_ROM_PTR(&bluetooth_ble_invoke_irq_obj)), mp_const_none); + mp_sched_schedule(MP_OBJ_FROM_PTR(&bluetooth_ble_invoke_irq_obj), mp_const_none); } } @@ -1071,7 +1071,7 @@ bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_han mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth)); if ((o->irq_trigger & MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST) && o->irq_handler != mp_const_none) { // Use pre-allocated tuple because this is a hard IRQ. - mp_obj_tuple_t *data = MP_OBJ_FROM_PTR(o->irq_data_tuple); + mp_obj_tuple_t *data = MP_OBJ_TO_PTR(o->irq_data_tuple); data->items[0] = MP_OBJ_NEW_SMALL_INT(conn_handle); data->items[1] = MP_OBJ_NEW_SMALL_INT(value_handle); data->len = 2; diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index c92d1dc1b0631..b5324316d3548 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -104,7 +104,7 @@ STATIC mp_obj_t webrepl_make_new(const mp_obj_type_t *type, size_t n_args, size_ o->data_to_recv = 0; o->state = STATE_PASSWD; write_webrepl_str(args[0], SSTR(passwd_prompt)); - return o; + return MP_OBJ_FROM_PTR(o); } STATIC void check_file_op_finished(mp_obj_webrepl_t *self) { @@ -187,7 +187,7 @@ STATIC mp_uint_t webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int * STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { // We know that os.dupterm always calls with size = 1 assert(size == 1); - mp_obj_webrepl_t *self = self_in; + mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(self_in); const mp_stream_p_t *sock_stream = mp_get_stream(self->sock); mp_uint_t out_sz = sock_stream->read(self->sock, buf, size, errcode); //DEBUG_printf("webrepl: Read %d initial bytes from websocket\n", out_sz); @@ -294,7 +294,7 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int } STATIC mp_uint_t webrepl_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { - mp_obj_webrepl_t *self = self_in; + mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(self_in); if (self->state == STATE_PASSWD) { // Don't forward output until passwd is entered return size; From e83fc3260ef81b85a0724276086528a83abea0c8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 22:45:27 +1100 Subject: [PATCH 0836/1299] drivers/cyw43: Fix to build in nanbox mode. --- drivers/cyw43/cyw43_ctrl.c | 2 +- drivers/cyw43/cyw43_lwip.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cyw43/cyw43_ctrl.c b/drivers/cyw43/cyw43_ctrl.c index 3a8bbf8646f40..53601dac22839 100644 --- a/drivers/cyw43/cyw43_ctrl.c +++ b/drivers/cyw43/cyw43_ctrl.c @@ -252,7 +252,7 @@ STATIC const char *cyw43_async_event_name_table[89] = { STATIC void cyw43_dump_async_event(const cyw43_async_event_t *ev) { printf("[% 8d] ASYNC(%04x,", - mp_hal_ticks_ms(), + (int)mp_hal_ticks_ms(), (unsigned int)ev->flags ); if (ev->event_type < MP_ARRAY_SIZE(cyw43_async_event_name_table) diff --git a/drivers/cyw43/cyw43_lwip.c b/drivers/cyw43/cyw43_lwip.c index 8f4223029edc7..391dfbe9007c6 100644 --- a/drivers/cyw43/cyw43_lwip.c +++ b/drivers/cyw43/cyw43_lwip.c @@ -49,7 +49,7 @@ STATIC void cyw43_ethernet_trace(cyw43_t *self, struct netif *netif, size_t len, } if (self->trace_flags & CYW43_TRACE_MAC) { - printf("[% 8d] ETH%cX itf=%c%c len=%u", mp_hal_ticks_ms(), is_tx ? 'T' : 'R', netif->name[0], netif->name[1], len); + printf("[% 8d] ETH%cX itf=%c%c len=%u", (int)mp_hal_ticks_ms(), is_tx ? 'T' : 'R', netif->name[0], netif->name[1], len); printf(" MAC type=%d subtype=%d data=", buf[0] >> 2 & 3, buf[0] >> 4); for (size_t i = 0; i < len; ++i) { printf(" %02x", buf[i]); From d980d51807465dd0f1e5835d483fe975c94a51a3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 22:46:43 +1100 Subject: [PATCH 0837/1299] stm32: Fix to build in nanbox mode. --- ports/stm32/machine_i2c.c | 2 +- ports/stm32/machine_timer.c | 6 +++--- ports/stm32/mpconfigport.h | 2 +- ports/stm32/mphalport.c | 5 +++-- ports/stm32/nimble_hci_uart.c | 2 +- ports/stm32/pyb_can.c | 2 +- ports/stm32/pyb_i2c.c | 2 +- ports/stm32/storage.c | 2 +- 8 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c index 5c74745591451..9b1f3f77f22a0 100644 --- a/ports/stm32/machine_i2c.c +++ b/ports/stm32/machine_i2c.c @@ -203,7 +203,7 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2C_POLL_DEFAULT_TIMEOUT_US} }, #if MACHINE_I2C_TIMINGR - { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, #endif }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c index 49e3a54d01a7d..22fa67d7d9d69 100644 --- a/ports/stm32/machine_timer.c +++ b/ports/stm32/machine_timer.c @@ -33,7 +33,7 @@ typedef soft_timer_entry_t machine_timer_obj_t; const mp_obj_type_t machine_timer_type; STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_timer_obj_t *self = self_in; + machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in); qstr mode = self->mode == SOFT_TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC; mp_printf(print, "Timer(mode=%q, period=%u)", mode, self->delta_ms); } @@ -42,10 +42,10 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_ar enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, }; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SOFT_TIMER_MODE_PERIODIC} }, - { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} }, { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, }; // Parse args diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index becde2b919c0e..4b5b0e054fbf7 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -301,7 +301,7 @@ struct _mp_bluetooth_nimble_root_pointers_t; // type definitions for the specific machine -#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) +#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((uint32_t)(p) | 1)) #define MP_SSIZE_MAX (0x7fffffff) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index aa5dc33975030..c8d83be0a1401 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -23,9 +23,10 @@ NORETURN void mp_hal_raise(HAL_StatusTypeDef status) { MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if (MP_STATE_PORT(pyb_stdio_uart) != NULL) { + mp_obj_t pyb_stdio_uart = MP_OBJ_FROM_PTR(MP_STATE_PORT(pyb_stdio_uart)); int errcode; - const mp_stream_p_t *stream_p = mp_get_stream(MP_STATE_PORT(pyb_stdio_uart)); - ret = stream_p->ioctl(MP_STATE_PORT(pyb_stdio_uart), MP_STREAM_POLL, poll_flags, &errcode); + const mp_stream_p_t *stream_p = mp_get_stream(pyb_stdio_uart); + ret = stream_p->ioctl(pyb_stdio_uart, MP_STREAM_POLL, poll_flags, &errcode); } return ret | mp_uos_dupterm_poll(poll_flags); } diff --git a/ports/stm32/nimble_hci_uart.c b/ports/stm32/nimble_hci_uart.c index 69e89e6abf6d5..e2ba00c017134 100644 --- a/ports/stm32/nimble_hci_uart.c +++ b/ports/stm32/nimble_hci_uart.c @@ -109,7 +109,7 @@ int nimble_hci_uart_configure(uint32_t port) { int nimble_hci_uart_activate(void) { // Interrupt on RX chunk received (idle) // Trigger nimble poll when this happens - mp_obj_t uart_irq_fn = mp_load_attr(&bt_hci_uart_obj, MP_QSTR_irq); + mp_obj_t uart_irq_fn = mp_load_attr(MP_OBJ_FROM_PTR(&bt_hci_uart_obj), MP_QSTR_irq); mp_obj_t uargs[] = { MP_OBJ_FROM_PTR(&mp_uart_interrupt_obj), MP_OBJ_NEW_SMALL_INT(UART_FLAG_IDLE), diff --git a/ports/stm32/pyb_can.c b/ports/stm32/pyb_can.c index 8b58da216100a..996816b6a2160 100644 --- a/ports/stm32/pyb_can.c +++ b/ports/stm32/pyb_can.c @@ -563,7 +563,7 @@ STATIC mp_obj_t pyb_can_initfilterbanks(mp_obj_t self, mp_obj_t bank_in) { #endif for (int f = 0; f < CAN_MAX_FILTER; f++) { - can_clearfilter(self, f, can2_start_bank); + can_clearfilter(MP_OBJ_TO_PTR(self), f, can2_start_bank); } return mp_const_none; } diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c index 8b816a25b135e..d503e6266433b 100644 --- a/ports/stm32/pyb_i2c.c +++ b/ports/stm32/pyb_i2c.c @@ -599,7 +599,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, co { MP_QSTR_gencall, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_dma, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, #if PYB_I2C_TIMINGR - { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_timingr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, #endif }; diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c index ebb62e44cfe57..7e131f02a81ba 100644 --- a/ports/stm32/storage.c +++ b/ports/stm32/storage.c @@ -365,7 +365,7 @@ STATIC mp_obj_t pyb_flash_writeblocks(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_flash_writeblocks_obj, 3, 4, pyb_flash_writeblocks); STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) { - pyb_flash_obj_t *self = self_in; + pyb_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t cmd = mp_obj_get_int(cmd_in); switch (cmd) { case MP_BLOCKDEV_IOCTL_INIT: { From 93509ac8c7ea7ac92b8b95453e7c5f13dcbc7099 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 22:47:01 +1100 Subject: [PATCH 0838/1299] stm32: Add configuration to build in nanbox mode. Most stm32 boards can now be built in nan-boxing mode via: $ make NANBOX=1 Note that if float is enabled then it will be forced to double-precision. Also, native emitters will be disabled. --- ports/stm32/Makefile | 9 +++++++ ports/stm32/mpconfigport.h | 5 +++- ports/stm32/mpconfigport_nanbox.h | 43 +++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 ports/stm32/mpconfigport_nanbox.h diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index c9fdc7b0d2bf5..6a6242df53305 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -95,6 +95,15 @@ CFLAGS += -I$(BOARD_DIR) CFLAGS += -DSTM32_HAL_H='' CFLAGS += -DMICROPY_HW_VTOR=$(TEXT0_ADDR) +# Configure for nan-boxing object model if requested +ifeq ($(NANBOX),1) +CFLAGS += -DMP_CONFIGFILE='"mpconfigport_nanbox.h"' +ifneq ($(MICROPY_FLOAT_IMPL),none) +MICROPY_FLOAT_IMPL = double +endif +endif + +# Configure floating point support ifeq ($(MICROPY_FLOAT_IMPL),double) CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE else diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 4b5b0e054fbf7..52cca0dca1fdd 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -305,11 +305,14 @@ struct _mp_bluetooth_nimble_root_pointers_t; #define MP_SSIZE_MAX (0x7fffffff) +// Assume that if we already defined the obj repr then we also defined these items +#ifndef MICROPY_OBJ_REPR #define UINT_FMT "%u" #define INT_FMT "%d" - typedef int mp_int_t; // must be pointer size typedef unsigned int mp_uint_t; // must be pointer size +#endif + typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) diff --git a/ports/stm32/mpconfigport_nanbox.h b/ports/stm32/mpconfigport_nanbox.h new file mode 100644 index 0000000000000..f36d55aca9b4c --- /dev/null +++ b/ports/stm32/mpconfigport_nanbox.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +// Select nan-boxing object model +#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) + +// Native emitters don't work with nan-boxing +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) + +// Types needed for nan-boxing +#define UINT_FMT "%llu" +#define INT_FMT "%lld" +typedef int64_t mp_int_t; +typedef uint64_t mp_uint_t; + +// Include base configuration file for rest of configuration +#include From e83ab7374bf1e8ee7b0644eb35567e30e6c21c36 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 22:48:44 +1100 Subject: [PATCH 0839/1299] travis: Add stm32 build in nanbox mode. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8ecc9f09bbefc..376e7b88e34a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,7 @@ jobs: - make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 + - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF6 NANBOX=1 - make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' - make ${MAKEOPTS} -C ports/stm32 BOARD=B_L072Z_LRWAN1 - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32L476DISC From 4c0176d13fbd99196c457cb38633040426efd758 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 23:15:52 +1100 Subject: [PATCH 0840/1299] py/objstr: Don't use inline GET_STR_DATA_LEN for object-repr D. Changing to use the helper function mp_obj_str_get_data_no_check() reduces code size of nan-boxing builds by about 1000 bytes. --- py/objstr.c | 6 +++--- py/objstr.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/py/objstr.c b/py/objstr.c index e221982c576e0..822c9fc418337 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2153,13 +2153,13 @@ const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len) { } } -#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C +#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len) { if (mp_obj_is_qstr(self_in)) { return qstr_data(MP_OBJ_QSTR_VALUE(self_in), len); } else { - *len = ((mp_obj_str_t*)self_in)->len; - return ((mp_obj_str_t*)self_in)->data; + *len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(self_in))->len; + return ((mp_obj_str_t*)MP_OBJ_TO_PTR(self_in))->data; } } #endif diff --git a/py/objstr.h b/py/objstr.h index 15ed7a2256015..ba300ccf5d5d3 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -50,7 +50,7 @@ typedef struct _mp_obj_str_t { { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->len; } // use this macro to extract the string data and length -#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C +#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len); #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \ size_t str_len; const byte *str_data = mp_obj_str_get_data_no_check(str_obj_in, &str_len); From d56bc6e03d842b1a2c91c987ba936752d0c2fe1b Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Dec 2019 23:33:34 +1100 Subject: [PATCH 0841/1299] py/obj.h: Use 32-bit shift in MP_OBJ_NEW_QSTR calc for obj-repr D. The qst value is always small enough to fit in 31-bits (even less) and using a 32-bit shift rather than a 64-bit shift reduces code size by about 300 bytes. --- py/obj.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/obj.h b/py/obj.h index b4ee911084ccd..efeb14b4330db 100644 --- a/py/obj.h +++ b/py/obj.h @@ -178,7 +178,7 @@ static inline bool mp_obj_is_small_int(mp_const_obj_t o) static inline bool mp_obj_is_qstr(mp_const_obj_t o) { return ((((uint64_t)(o)) & 0xffff000000000000) == 0x0002000000000000); } #define MP_OBJ_QSTR_VALUE(o) ((((uint32_t)(o)) >> 1) & 0xffffffff) -#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 1) | 0x0002000000000001)) +#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)(((uint64_t)(((uint32_t)(qst)) << 1)) | 0x0002000000000001)) #if MICROPY_PY_BUILTINS_FLOAT From e79424d672919bfc59862d14f2d9e78e43e8582e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 21 Dec 2019 14:22:26 -0600 Subject: [PATCH 0842/1299] ports: Allow overriding CROSS_COMPILE in a custom makefile. Many ports already allow overriding CROSS_COMPILE. This modifies the remaining ports to allow it as well. --- ports/bare-arm/Makefile | 2 +- ports/esp8266/Makefile | 2 +- ports/minimal/Makefile | 2 +- ports/nrf/Makefile | 2 +- ports/pic16bit/Makefile | 2 +- ports/powerpc/Makefile | 2 +- ports/stm32/mboot/Makefile | 2 +- ports/teensy/Makefile | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ports/bare-arm/Makefile b/ports/bare-arm/Makefile index 7cb3432819193..800f4093dfeaf 100644 --- a/ports/bare-arm/Makefile +++ b/ports/bare-arm/Makefile @@ -6,7 +6,7 @@ QSTR_DEFS = qstrdefsport.h # include py core make definitions include $(TOP)/py/py.mk -CROSS_COMPILE = arm-none-eabi- +CROSS_COMPILE ?= arm-none-eabi- INC += -I. INC += -I$(TOP) diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index f534eb6895073..9a7476c10210a 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -39,7 +39,7 @@ PORT ?= /dev/ttyACM0 BAUD ?= 115200 FLASH_MODE ?= qio FLASH_SIZE ?= detect -CROSS_COMPILE = xtensa-lx106-elf- +CROSS_COMPILE ?= xtensa-lx106-elf- ESP_SDK = $(shell $(CC) -print-sysroot)/usr INC += -I. diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile index f26a7ec97d5e7..d8afa068d8682 100644 --- a/ports/minimal/Makefile +++ b/ports/minimal/Makefile @@ -9,7 +9,7 @@ QSTR_DEFS = qstrdefsport.h include $(TOP)/py/py.mk ifeq ($(CROSS), 1) -CROSS_COMPILE = arm-none-eabi- +CROSS_COMPILE ?= arm-none-eabi- endif INC += -I. diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 2ac654911e3a9..836a89c202f83 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -47,7 +47,7 @@ MICROPY_VFS_FAT ?= 0 MPY_CROSS = ../../mpy-cross/mpy-cross MPY_TOOL = ../../tools/mpy-tool.py -CROSS_COMPILE = arm-none-eabi- +CROSS_COMPILE ?= arm-none-eabi- INC += -I. INC += -I../.. diff --git a/ports/pic16bit/Makefile b/ports/pic16bit/Makefile index 8a931979d2986..fa6de38e39274 100644 --- a/ports/pic16bit/Makefile +++ b/ports/pic16bit/Makefile @@ -7,7 +7,7 @@ QSTR_DEFS = qstrdefsport.h include $(TOP)/py/py.mk XC16 = /opt/microchip/xc16/v1.35 -CROSS_COMPILE = $(XC16)/bin/xc16- +CROSS_COMPILE ?= $(XC16)/bin/xc16- PARTFAMILY = dsPIC33F PART = 33FJ256GP506 diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile index 30474df1d1673..d869ebc4f16d0 100644 --- a/ports/powerpc/Makefile +++ b/ports/powerpc/Makefile @@ -9,7 +9,7 @@ include $(TOP)/py/py.mk ARCH = $(shell uname -m) ifneq ("$(ARCH)", "ppc64") ifneq ("$(ARCH)", "ppc64le") - CROSS_COMPILE = powerpc64le-linux- + CROSS_COMPILE ?= powerpc64le-linux- endif endif diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 19635b9183ed6..9e56733005979 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -34,7 +34,7 @@ OPENOCD ?= openocd OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg STARTUP_FILE ?= lib/stm32lib/CMSIS/STM32$(MCU_SERIES_UPPER)xx/Source/Templates/gcc/startup_$(CMSIS_MCU_LOWER).o -CROSS_COMPILE = arm-none-eabi- +CROSS_COMPILE ?= arm-none-eabi- INC += -I. INC += -I.. diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile index 663a86fabd7af..769b7e39d75d2 100644 --- a/ports/teensy/Makefile +++ b/ports/teensy/Makefile @@ -20,10 +20,10 @@ endif ifeq ($(USE_ARDUINO_TOOLCHAIN),1) $(info Using ARDUINO toolchain) -CROSS_COMPILE = $(ARDUINO)/hardware/tools/arm-none-eabi/bin/arm-none-eabi- +CROSS_COMPILE ?= $(ARDUINO)/hardware/tools/arm-none-eabi/bin/arm-none-eabi- else $(info Using toolchain from PATH) -CROSS_COMPILE = arm-none-eabi- +CROSS_COMPILE ?= arm-none-eabi- endif CFLAGS_TEENSY = -DF_CPU=96000000 -DUSB_SERIAL -D__MK20DX256__ From aca8873bb841860c0b62d36afe42501eb4505199 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sun, 1 Dec 2019 01:07:58 +0200 Subject: [PATCH 0843/1299] extmod/modbluetooth: Fix func prototype, empty args should be (void). This fixes a -Wstrict-prototypes error. --- extmod/modbluetooth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index fbae67bc4546b..074f53b978af6 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -180,7 +180,7 @@ int mp_bluetooth_gatts_register_service_begin(bool append); // The value_handles won't be valid until after mp_bluetooth_register_service_end is called. int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics); // Register any queued services. -int mp_bluetooth_gatts_register_service_end(); +int mp_bluetooth_gatts_register_service_end(void); // Read the value from the local gatts db (likely this has been written by a central). int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len); From 61d2b40ad56243585ac2bebef67aff10d4c5583c Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 25 Dec 2019 09:27:38 +0200 Subject: [PATCH 0844/1299] lib/utils/pyexec: Introduce MICROPY_REPL_INFO, wrap debug prints in it. For the 3 ports that already make use of this feature (stm32, nrf and teensy) this doesn't make any difference, it just allows to disable it from now on. For other ports that use pyexec, this decreases code size because the debug printing code is dead (it can't be enabled) but the compiler can't deduce that, so code is still emitted. --- lib/utils/pyexec.c | 12 +++++++++++- lib/utils/pyexec.h | 4 +++- ports/nrf/modules/board/modboard.c | 2 ++ ports/nrf/mpconfigport.h | 1 + ports/stm32/modpyb.c | 2 ++ ports/stm32/mpconfigport.h | 1 + ports/teensy/modpyb.c | 2 ++ ports/teensy/mpconfigport.h | 1 + py/mpconfig.h | 5 +++++ 9 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index 851b026b6fd35..747097f157015 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -45,7 +45,10 @@ pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; int pyexec_system_exit = 0; + +#if MICROPY_REPL_INFO STATIC bool repl_display_debugging_info = 0; +#endif #define EXEC_FLAG_PRINT_EOF (1) #define EXEC_FLAG_ALLOW_DEBUGGING (2) @@ -61,7 +64,9 @@ STATIC bool repl_display_debugging_info = 0; // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, int exec_flags) { int ret = 0; + #if MICROPY_REPL_INFO uint32_t start = 0; + #endif // by default a SystemExit exception returns 0 pyexec_system_exit = 0; @@ -97,7 +102,9 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input // execute code mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us + #if MICROPY_REPL_INFO start = mp_hal_ticks_ms(); + #endif mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt nlr_pop(); @@ -123,6 +130,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input } } + #if MICROPY_REPL_INFO // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { mp_uint_t ticks = mp_hal_ticks_ms() - start; // TODO implement a function that does this properly @@ -142,6 +150,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input gc_dump_info(); #endif } + #endif if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); @@ -576,9 +585,10 @@ int pyexec_frozen_module(const char *name) { } #endif +#if MICROPY_REPL_INFO mp_obj_t pyb_set_repl_info(mp_obj_t o_value) { repl_display_debugging_info = mp_obj_get_int(o_value); return mp_const_none; } - MP_DEFINE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj, pyb_set_repl_info); +#endif diff --git a/lib/utils/pyexec.h b/lib/utils/pyexec.h index 9eb490be543fd..573cb6d452ada 100644 --- a/lib/utils/pyexec.h +++ b/lib/utils/pyexec.h @@ -51,8 +51,10 @@ int pyexec_frozen_module(const char *name); void pyexec_event_repl_init(void); int pyexec_event_repl_process_char(int c); extern uint8_t pyexec_repl_active; -mp_obj_t pyb_set_repl_info(mp_obj_t o_value); +#if MICROPY_REPL_INFO +mp_obj_t pyb_set_repl_info(mp_obj_t o_value); MP_DECLARE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj); +#endif #endif // MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H diff --git a/ports/nrf/modules/board/modboard.c b/ports/nrf/modules/board/modboard.c index 354a6169673c1..5f59a52a6b868 100644 --- a/ports/nrf/modules/board/modboard.c +++ b/ports/nrf/modules/board/modboard.c @@ -40,7 +40,9 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_board) }, + #if MICROPY_REPL_INFO { MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) }, + #endif PYB_LED_MODULE }; diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index e5fa1579c5751..281d8111cf789 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -44,6 +44,7 @@ #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_INFO (1) #define MICROPY_REPL_EMACS_KEYS (0) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_KBD_EXCEPTION (1) diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index 71d7849233293..6dbfb1e0bd26e 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -142,7 +142,9 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, #endif + #if MICROPY_REPL_INFO { MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_wfi), MP_ROM_PTR(&pyb_wfi_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) }, diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 52cca0dca1fdd..7ae8ee7d72112 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -70,6 +70,7 @@ #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0) #define MICROPY_KBD_EXCEPTION (1) #define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_INFO (1) #define MICROPY_REPL_EMACS_KEYS (1) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) diff --git a/ports/teensy/modpyb.c b/ports/teensy/modpyb.c index e4c399fc84326..6d637a7c25452 100644 --- a/ports/teensy/modpyb.c +++ b/ports/teensy/modpyb.c @@ -283,7 +283,9 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_info_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&pyb_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_freq_obj) }, + #if MICROPY_REPL_INFO { MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) }, + #endif { MP_ROM_QSTR(MP_QSTR_wfi), MP_ROM_PTR(&pyb_wfi_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) }, diff --git a/ports/teensy/mpconfigport.h b/ports/teensy/mpconfigport.h index b45b5ad4e3c5a..a75bd6849a235 100644 --- a/ports/teensy/mpconfigport.h +++ b/ports/teensy/mpconfigport.h @@ -9,6 +9,7 @@ #define MICROPY_ENABLE_FINALISER (1) #define MICROPY_STACK_CHECK (1) #define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_INFO (1) #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) diff --git a/py/mpconfig.h b/py/mpconfig.h index 1e786f753b6d6..93d67accdb8c4 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -560,6 +560,11 @@ #define MICROPY_HELPER_REPL (0) #endif +// Allow enabling debug prints after each REPL line +#ifndef MICROPY_REPL_INFO +#define MICROPY_REPL_INFO (0) +#endif + // Whether to include emacs-style readline behavior in REPL #ifndef MICROPY_REPL_EMACS_KEYS #define MICROPY_REPL_EMACS_KEYS (0) From b2e4a57289d17d6d4377880c5fc143b3d51f3678 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 25 Dec 2019 09:22:40 +0200 Subject: [PATCH 0845/1299] nrf/main: Remove unnecessary repl_info(0) call. It's statically initialized to 0. --- ports/nrf/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/nrf/main.c b/ports/nrf/main.c index 9ffe7a285c9e0..af5991281f16b 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -121,8 +121,6 @@ int main(int argc, char **argv) { mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) mp_obj_list_init(mp_sys_argv, 0); - pyb_set_repl_info(MP_OBJ_NEW_SMALL_INT(0)); - readline_init0(); From b23bd6433cd68830d32c0c68dbbf554942bb6ad0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 28 Dec 2019 01:01:36 +1100 Subject: [PATCH 0846/1299] py: Clean up commented-out code and comments about exception hierarchy. In CPython, EnvironmentError and IOError are now aliases of OSError so no need to have them listed in the code. OverflowError inherits from ArithmeticError because it's intended to be raised "when the result of an arithmetic operation is too large to be represented" (per CPython docs), and MicroPython aims to match the CPython exception hierarchy. --- py/modbuiltins.c | 2 -- py/objexcept.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/py/modbuiltins.c b/py/modbuiltins.c index a65f3beecfa8b..5a0a3a33803d7 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -762,8 +762,6 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ViperTypeError), MP_ROM_PTR(&mp_type_ViperTypeError) }, #endif { MP_ROM_QSTR(MP_QSTR_ZeroDivisionError), MP_ROM_PTR(&mp_type_ZeroDivisionError) }, - // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ - // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation // Extra builtins as defined by a port MICROPY_PORT_BUILTINS diff --git a/py/objexcept.c b/py/objexcept.c index dadbe98ae8311..869a80bbe783f 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -241,10 +241,8 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) MP_DEFINE_EXCEPTION(AssertionError, Exception) MP_DEFINE_EXCEPTION(AttributeError, Exception) //MP_DEFINE_EXCEPTION(BufferError, Exception) - //MP_DEFINE_EXCEPTION(EnvironmentError, Exception) use OSError instead MP_DEFINE_EXCEPTION(EOFError, Exception) MP_DEFINE_EXCEPTION(ImportError, Exception) - //MP_DEFINE_EXCEPTION(IOError, Exception) use OSError instead MP_DEFINE_EXCEPTION(LookupError, Exception) MP_DEFINE_EXCEPTION(IndexError, LookupError) MP_DEFINE_EXCEPTION(KeyError, LookupError) From 1b844e908c3a867be1e54efdb86a04c6a62b2f26 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 26 Nov 2019 11:02:19 +1100 Subject: [PATCH 0847/1299] unix/modtime: Add utime.mktime function, to complement utime.localtime. This also adds it to the windows port. --- ports/unix/modtime.c | 32 ++++++++++++++++++++++++++++++++ tests/unix/time.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 tests/unix/time.py diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c index 0a463014dc0cb..479d2a79dd904 100644 --- a/ports/unix/modtime.c +++ b/ports/unix/modtime.c @@ -161,6 +161,37 @@ STATIC mp_obj_t mod_time_localtime(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_localtime_obj, 0, 1, mod_time_localtime); +STATIC mp_obj_t mod_time_mktime(mp_obj_t tuple) { + size_t len; + mp_obj_t *elem; + mp_obj_get_array(tuple, &len, &elem); + + // localtime generates a tuple of len 8. CPython uses 9, so we accept both. + if (len < 8 || len > 9) { + mp_raise_TypeError("mktime needs a tuple of length 8 or 9"); + } + + struct tm time = { + .tm_year = mp_obj_get_int(elem[0]) - 1900, + .tm_mon = mp_obj_get_int(elem[1]) - 1, + .tm_mday = mp_obj_get_int(elem[2]), + .tm_hour = mp_obj_get_int(elem[3]), + .tm_min = mp_obj_get_int(elem[4]), + .tm_sec = mp_obj_get_int(elem[5]), + }; + if (len == 9) { + time.tm_isdst = mp_obj_get_int(elem[8]); + } else { + time.tm_isdst = -1; // auto-detect + } + time_t ret = mktime(&time); + if (ret == -1) { + mp_raise_msg(&mp_type_OverflowError, "invalid mktime usage"); + } + return mp_obj_new_int(ret); +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_time_mktime_obj, mod_time_mktime); + STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, { MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&mod_time_clock_obj) }, @@ -174,6 +205,7 @@ STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mod_time_localtime_obj) }, + { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&mod_time_mktime_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); diff --git a/tests/unix/time.py b/tests/unix/time.py new file mode 100644 index 0000000000000..a96c3f5b66aa7 --- /dev/null +++ b/tests/unix/time.py @@ -0,0 +1,44 @@ +try: + import utime as time +except ImportError: + import time + +DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + +tzseconds = -time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0)) + +def is_leap(year): + return (year % 4) == 0 + +def test(): + seconds = 0 + wday = 3 # Jan 1, 1970 was a Thursday + for year in range(1970, 2038): + print("Testing %d" % year) + yday = 1 + for month in range(1, 13): + if month == 2 and is_leap(year): + DAYS_PER_MONTH[2] = 29 + else: + DAYS_PER_MONTH[2] = 28 + for day in range(1, DAYS_PER_MONTH[month] + 1): + secs = time.mktime((year, month, day, 0, 0, 0, 0, 0, 0)) + tzseconds + if secs != seconds: + print("mktime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds)) + return + tuple = time.localtime(seconds) + secs = time.mktime(tuple) + if secs != seconds: + print("localtime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds)) + return + seconds += 86400 + if yday != tuple[7]: + print("locatime for %d-%02d-%02d got yday %d, expecting %d" % (year, month, day, tuple[7], yday)) + return + if wday != tuple[6]: + print("locatime for %d-%02d-%02d got wday %d, expecting %d" % (year, month, day, tuple[6], wday)) + return + yday += 1 + wday = (wday + 1) % 7 + +test() From 269c9a08b6ac248b7bd67d4fa56f70791b5b7a73 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 28 Dec 2019 11:54:49 +1100 Subject: [PATCH 0848/1299] unix/modos: Add uos.rename and uos.rmdir. The existing uos.remove cannot be used to remove directories, instead uos.rmdir is needed. And also provide uos.rename to get a good set of filesystem functionality without requiring additional Python-level os functions (eg using ffi). --- ports/unix/modos.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ports/unix/modos.c b/ports/unix/modos.c index 161918d4dcec4..c3b0c20b2b007 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,29 @@ STATIC mp_obj_t mod_os_remove(mp_obj_t path_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_remove_obj, mod_os_remove); +STATIC mp_obj_t mod_os_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) { + const char *old_path = mp_obj_str_get_str(old_path_in); + const char *new_path = mp_obj_str_get_str(new_path_in); + + int r = rename(old_path, new_path); + + RAISE_ERRNO(r, errno); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_os_rename_obj, mod_os_rename); + +STATIC mp_obj_t mod_os_rmdir(mp_obj_t path_in) { + const char *path = mp_obj_str_get_str(path_in); + + int r = rmdir(path); + + RAISE_ERRNO(r, errno); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_rmdir_obj, mod_os_rmdir); + STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { const char *cmd = mp_obj_str_get_str(cmd_in); @@ -236,6 +260,8 @@ STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mod_os_system_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mod_os_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mod_os_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mod_os_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) }, From 007a704d82f07d1482dae6f265fecf5710266767 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 28 Dec 2019 10:36:59 +1100 Subject: [PATCH 0849/1299] nrf/examples: Fix typo in mountsd.py, wireing -> wiring. --- ports/nrf/examples/mountsd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/nrf/examples/mountsd.py b/ports/nrf/examples/mountsd.py index 64e1c888bea18..037b3258c5344 100644 --- a/ports/nrf/examples/mountsd.py +++ b/ports/nrf/examples/mountsd.py @@ -4,7 +4,7 @@ and list a sdcard connected over SPI. -Direct wireing on SD card (SPI): +Direct wiring on SD card (SPI): ______________________________ | \ | 9. | NC | \ From 4c93955b7b4d3d860aed1551ca6231ac4e388e69 Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Sat, 16 Nov 2019 17:07:11 -0700 Subject: [PATCH 0850/1299] py/objslice: Add support for indices() method on slice objects. Instances of the slice class are passed to __getitem__() on objects when the user indexes them with a slice. In practice the majority of the time (other than passing it on untouched) is to work out what the slice means in the context of an array dimension of a particular length. Since Python 2.3 there has been a method on the slice class, indices(), that takes a dimension length and returns the real start, stop and step, accounting for missing or negative values in the slice spec. This commit implements such a indices() method on the slice class. It is configurable at compile-time via MICROPY_PY_BUILTINS_SLICE_INDICES, disabled by default, enabled on unix, stm32 and esp32 ports. This commit also adds new tests for slice indices and for slicing unicode strings. --- ports/esp32/mpconfigport.h | 1 + ports/stm32/mpconfigport.h | 1 + ports/unix/mpconfigport.h | 1 + py/mpconfig.h | 5 ++ py/obj.h | 15 +++--- py/objslice.c | 98 +++++++++++++++++++++++++++++++++- py/sequence.c | 74 +++---------------------- tests/basics/slice_indices.py | 27 ++++++++++ tests/unicode/unicode_slice.py | 12 +++++ 9 files changed, 160 insertions(+), 74 deletions(-) create mode 100644 tests/basics/slice_indices.py create mode 100644 tests/unicode/unicode_slice.py diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 1924cf21860a5..983c882ae8aca 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -73,6 +73,7 @@ #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) +#define MICROPY_PY_BUILTINS_SLICE_INDICES (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 7ae8ee7d72112..55f09f81f09f1 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -97,6 +97,7 @@ #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) +#define MICROPY_PY_BUILTINS_SLICE_INDICES (1) #define MICROPY_PY_BUILTINS_ROUND_INT (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_BUILTINS_COMPILE (MICROPY_ENABLE_COMPILER) diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 40cd1f570252c..d633726a16a78 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -90,6 +90,7 @@ #define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) +#define MICROPY_PY_BUILTINS_SLICE_INDICES (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_ATEXIT (1) #if MICROPY_PY_SYS_SETTRACE diff --git a/py/mpconfig.h b/py/mpconfig.h index 93d67accdb8c4..d6f4d9232860d 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -894,6 +894,11 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) #endif +// Whether to support the .indices(len) method on slice objects +#ifndef MICROPY_PY_BUILTINS_SLICE_INDICES +#define MICROPY_PY_BUILTINS_SLICE_INDICES (0) +#endif + // Whether to support frozenset object #ifndef MICROPY_PY_BUILTINS_FROZENSET #define MICROPY_PY_BUILTINS_FROZENSET (0) diff --git a/py/obj.h b/py/obj.h index efeb14b4330db..ab5b1e6ec0400 100644 --- a/py/obj.h +++ b/py/obj.h @@ -778,8 +778,16 @@ static inline mp_map_t *mp_obj_dict_get_map(mp_obj_t dict) { // set void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item); +// slice indexes resolved to particular sequence +typedef struct { + mp_int_t start; + mp_int_t stop; + mp_int_t step; +} mp_bound_slice_t; + // slice void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step); +void mp_obj_slice_indices(mp_obj_t self_in, mp_int_t length, mp_bound_slice_t *result); // functions @@ -836,13 +844,6 @@ const mp_obj_t *mp_obj_property_get(mp_obj_t self_in); // sequence helpers -// slice indexes resolved to particular sequence -typedef struct { - mp_uint_t start; - mp_uint_t stop; - mp_int_t step; -} mp_bound_slice_t; - void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest); #if MICROPY_PY_BUILTINS_SLICE bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes); diff --git a/py/objslice.c b/py/objslice.c index cfc819edccb25..d17dbf6057b52 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -27,7 +27,7 @@ #include #include -#include "py/obj.h" +#include "py/runtime.h" /******************************************************************************/ /* slice object */ @@ -53,6 +53,22 @@ STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t mp_print_str(print, ")"); } +#if MICROPY_PY_BUILTINS_SLICE_INDICES +STATIC mp_obj_t slice_indices(mp_obj_t self_in, mp_obj_t length_obj) { + mp_int_t length = mp_obj_int_get_checked(length_obj); + mp_bound_slice_t bound_indices; + mp_obj_slice_indices(self_in, length, &bound_indices); + + mp_obj_t results[3] = { + MP_OBJ_NEW_SMALL_INT(bound_indices.start), + MP_OBJ_NEW_SMALL_INT(bound_indices.stop), + MP_OBJ_NEW_SMALL_INT(bound_indices.step), + }; + return mp_obj_new_tuple(3, results); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(slice_indices_obj, slice_indices); +#endif + #if MICROPY_PY_BUILTINS_SLICE_ATTRS STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { @@ -60,22 +76,37 @@ STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { return; } mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in); + if (attr == MP_QSTR_start) { dest[0] = self->start; } else if (attr == MP_QSTR_stop) { dest[0] = self->stop; } else if (attr == MP_QSTR_step) { dest[0] = self->step; + #if MICROPY_PY_BUILTINS_SLICE_INDICES + } else if (attr == MP_QSTR_indices) { + dest[0] = MP_OBJ_FROM_PTR(&slice_indices_obj); + dest[1] = self_in; + #endif } } #endif +#if MICROPY_PY_BUILTINS_SLICE_INDICES && !MICROPY_PY_BUILTINS_SLICE_ATTRS +STATIC const mp_rom_map_elem_t slice_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_indices), MP_ROM_PTR(&slice_indices_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(slice_locals_dict, slice_locals_dict_table); +#endif + const mp_obj_type_t mp_type_slice = { { &mp_type_type }, .name = MP_QSTR_slice, .print = slice_print, #if MICROPY_PY_BUILTINS_SLICE_ATTRS .attr = slice_attr, +#elif MICROPY_PY_BUILTINS_SLICE_INDICES + .locals_dict = (mp_obj_dict_t*)&slice_locals_dict, #endif }; @@ -96,4 +127,69 @@ void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_ *step = self->step; } +// Return the real index and step values for a slice when applied to a sequence of +// the given length, resolving missing components, negative values and values off +// the end of the sequence. +void mp_obj_slice_indices(mp_obj_t self_in, mp_int_t length, mp_bound_slice_t *result) { + mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t start, stop, step; + + if (self->step == mp_const_none) { + step = 1; + } else { + step = mp_obj_get_int(self->step); + if (step == 0) { + mp_raise_ValueError("slice step cannot be zero"); + } + } + + if (step > 0) { + // Positive step + if (self->start == mp_const_none) { + start = 0; + } else { + start = mp_obj_get_int(self->start); + if (start < 0) { + start += length; + } + start = MIN(length, MAX(start, 0)); + } + + if (self->stop == mp_const_none) { + stop = length; + } else { + stop = mp_obj_get_int(self->stop); + if (stop < 0) { + stop += length; + } + stop = MIN(length, MAX(stop, 0)); + } + } else { + // Negative step + if (self->start == mp_const_none) { + start = length - 1; + } else { + start = mp_obj_get_int(self->start); + if (start < 0) { + start += length; + } + start = MIN(length - 1, MAX(start, -1)); + } + + if (self->stop == mp_const_none) { + stop = -1; + } else { + stop = mp_obj_get_int(self->stop); + if (stop < 0) { + stop += length; + } + stop = MIN(length - 1, MAX(stop, -1)); + } + } + + result->start = start; + result->stop = stop; + result->step = step; +} + #endif diff --git a/py/sequence.c b/py/sequence.c index 4c19fc69ea3d5..15e925000a17b 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -46,78 +46,20 @@ void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times #if MICROPY_PY_BUILTINS_SLICE bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) { - mp_obj_t ostart, ostop, ostep; - mp_int_t start, stop; - mp_obj_slice_get(slice, &ostart, &ostop, &ostep); + mp_obj_slice_indices(slice, len, indexes); - if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { - indexes->step = mp_obj_get_int(ostep); - if (indexes->step == 0) { - mp_raise_ValueError("slice step cannot be zero"); - } - } else { - indexes->step = 1; - } - - if (ostart == mp_const_none) { - if (indexes->step > 0) { - start = 0; - } else { - start = len - 1; - } - } else { - start = mp_obj_get_int(ostart); - } - if (ostop == mp_const_none) { - if (indexes->step > 0) { - stop = len; - } else { - stop = 0; - } - } else { - stop = mp_obj_get_int(ostop); - if (stop >= 0 && indexes->step < 0) { - stop += 1; - } - } - - // Unlike subscription, out-of-bounds slice indexes are never error - if (start < 0) { - start = len + start; - if (start < 0) { - if (indexes->step < 0) { - start = -1; - } else { - start = 0; - } - } - } else if (indexes->step > 0 && (mp_uint_t)start > len) { - start = len; - } else if (indexes->step < 0 && (mp_uint_t)start >= len) { - start = len - 1; - } - if (stop < 0) { - stop = len + stop; - if (stop < 0) { - stop = -1; - } - if (indexes->step < 0) { - stop += 1; - } - } else if ((mp_uint_t)stop > len) { - stop = len; + // If the index is negative then stop points to the last item, not after it + if (indexes->step < 0) { + indexes->stop++; } // CPython returns empty sequence in such case, or point for assignment is at start - if (indexes->step > 0 && start > stop) { - stop = start; - } else if (indexes->step < 0 && start < stop) { - stop = start + 1; + if (indexes->step > 0 && indexes->start > indexes->stop) { + indexes->stop = indexes->start; + } else if (indexes->step < 0 && indexes->start < indexes->stop) { + indexes->stop = indexes->start + 1; } - indexes->start = start; - indexes->stop = stop; - return indexes->step == 1; } diff --git a/tests/basics/slice_indices.py b/tests/basics/slice_indices.py new file mode 100644 index 0000000000000..b7f439ccca267 --- /dev/null +++ b/tests/basics/slice_indices.py @@ -0,0 +1,27 @@ +# Test builtin slice indices resolution + +# A class that returns an item key +class A: + def __getitem__(self, idx): + return idx + +# Make sure that we have slices and .indices() +try: + A()[2:5].indices(10) +except: + print("SKIP") + raise SystemExit + +print(A()[:].indices(10)) +print(A()[2:].indices(10)) +print(A()[:7].indices(10)) +print(A()[2:7].indices(10)) +print(A()[2:7:2].indices(10)) +print(A()[2:7:-2].indices(10)) +print(A()[7:2:2].indices(10)) +print(A()[7:2:-2].indices(10)) + +print(A()[2:7:2].indices(5)) +print(A()[2:7:-2].indices(5)) +print(A()[7:2:2].indices(5)) +print(A()[7:2:-2].indices(5)) diff --git a/tests/unicode/unicode_slice.py b/tests/unicode/unicode_slice.py new file mode 100644 index 0000000000000..d9237088f8097 --- /dev/null +++ b/tests/unicode/unicode_slice.py @@ -0,0 +1,12 @@ +# Test slicing of Unicode strings + +s = "Привет" + +print(s[:]) +print(s[2:]) +print(s[:5]) +print(s[2:5]) +print(s[2:5:1]) +print(s[2:10]) +print(s[-3:10]) +print(s[-4:10]) From 10709846f38f8f6519dee27694ce583926a00cb9 Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Wed, 20 Nov 2019 18:53:07 -0700 Subject: [PATCH 0851/1299] py/objslice: Inline fetching of slice paramters in str_subscr(). To reduce code size. --- py/obj.h | 7 ++++++- py/objslice.c | 15 --------------- py/objstrunicode.c | 6 +++++- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/py/obj.h b/py/obj.h index ab5b1e6ec0400..f1444749177b9 100644 --- a/py/obj.h +++ b/py/obj.h @@ -786,7 +786,12 @@ typedef struct { } mp_bound_slice_t; // slice -void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step); +typedef struct _mp_obj_slice_t { + mp_obj_base_t base; + mp_obj_t start; + mp_obj_t stop; + mp_obj_t step; +} mp_obj_slice_t; void mp_obj_slice_indices(mp_obj_t self_in, mp_int_t length, mp_bound_slice_t *result); // functions diff --git a/py/objslice.c b/py/objslice.c index d17dbf6057b52..86ee03ec518ea 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -34,13 +34,6 @@ #if MICROPY_PY_BUILTINS_SLICE -typedef struct _mp_obj_slice_t { - mp_obj_base_t base; - mp_obj_t start; - mp_obj_t stop; - mp_obj_t step; -} mp_obj_slice_t; - STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_slice_t *o = MP_OBJ_TO_PTR(o_in); @@ -119,14 +112,6 @@ mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) { return MP_OBJ_FROM_PTR(o); } -void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step) { - assert(mp_obj_is_type(self_in, &mp_type_slice)); - mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in); - *start = self->start; - *stop = self->stop; - *step = self->step; -} - // Return the real index and step values for a slice when applied to a sequence of // the given length, resolving missing components, negative values and values off // the end of the sequence. diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 78d0b5006ef73..5a127243bc089 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -184,7 +184,11 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_obj_t ostart, ostop, ostep; - mp_obj_slice_get(index, &ostart, &ostop, &ostep); + mp_obj_slice_t *slice = MP_OBJ_TO_PTR(index); + ostart = slice->start; + ostop = slice->stop; + ostep = slice->step; + if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported"); } From de78a9e317d3dd3654424ea70446dedbae9cce52 Mon Sep 17 00:00:00 2001 From: Jason Neal Date: Thu, 2 Jan 2020 00:30:18 +1300 Subject: [PATCH 0852/1299] tools/gen-cpydiff.py: Adjust subsections to sentence case. --- tools/gen-cpydiff.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen-cpydiff.py b/tools/gen-cpydiff.py index 8aef375149348..356ade89d5b49 100644 --- a/tools/gen-cpydiff.py +++ b/tools/gen-cpydiff.py @@ -51,7 +51,7 @@ HEADER = '.. This document was generated by tools/gen-cpydiff.py\n\n' UIMPORTLIST = {'struct', 'collections', 'json'} -CLASSMAP = {'Core': 'Core Language', 'Types': 'Builtin Types'} +CLASSMAP = {'Core': 'Core language', 'Types': 'Builtin types'} INDEXPRIORITY = ['syntax', 'core_language', 'builtin_types', 'modules'] RSTCHARS = ['=', '-', '~', '`', ':'] SPLIT = '"""\n|categories: |description: |cause: |workaround: ' From aec88ddf0326187c567d4e4507149fb7c54ba91d Mon Sep 17 00:00:00 2001 From: Jason Neal Date: Thu, 2 Jan 2020 00:51:42 +1300 Subject: [PATCH 0853/1299] docs: More consistent capitalization and use of articles in headings. See issue #3188. --- docs/develop/cmodules.rst | 2 +- docs/esp32/quickref.rst | 2 +- docs/library/esp32.rst | 4 ++-- docs/library/framebuf.rst | 2 +- docs/pyboard/tutorial/switch.rst | 4 ++-- docs/reference/asm_thumb2_directives.rst | 2 +- docs/reference/asm_thumb2_float.rst | 6 +++--- docs/reference/asm_thumb2_index.rst | 4 ++-- docs/reference/asm_thumb2_logical_bit.rst | 2 +- docs/reference/constrained.rst | 14 +++++++------- docs/reference/index.rst | 4 ++-- docs/reference/isr_rules.rst | 8 ++++---- docs/reference/repl.rst | 6 +++--- docs/reference/speed_python.rst | 6 +++--- 14 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs/develop/cmodules.rst b/docs/develop/cmodules.rst index a4c473347860b..e616adad03353 100644 --- a/docs/develop/cmodules.rst +++ b/docs/develop/cmodules.rst @@ -54,7 +54,7 @@ A MicroPython user C module is a directory with the following files: See below for full usage example. -Basic Example +Basic example ------------- This simple module named ``example`` provides a single function diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index cfe31664e74ea..c58f4aa760856 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -435,7 +435,7 @@ For low-level driving of a NeoPixel:: ``NeoPixel`` object. -Capacitive Touch +Capacitive touch ---------------- Use the ``TouchPad`` class in the ``machine`` module:: diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 467af0ff0f251..5df1f3c9317e1 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -173,8 +173,8 @@ For more details see Espressif's `ESP-IDF RMT documentation. stream starts at 0 or 1. -The Ultra-Low-Power co-processor --------------------------------- +Ultra-Low-Power co-processor +---------------------------- .. class:: ULP() diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index b6d7dba5de247..1ff56e4dae927 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -1,4 +1,4 @@ -:mod:`framebuf` --- Frame buffer manipulation +:mod:`framebuf` --- frame buffer manipulation ============================================= .. module:: framebuf diff --git a/docs/pyboard/tutorial/switch.rst b/docs/pyboard/tutorial/switch.rst index e2a5eae884819..96bb3784e9f8c 100644 --- a/docs/pyboard/tutorial/switch.rst +++ b/docs/pyboard/tutorial/switch.rst @@ -1,7 +1,7 @@ .. _pyboard_tutorial_switch: -The Switch, callbacks and interrupts -==================================== +Switches, callbacks and interrupts +================================== The pyboard has 2 small switches, labelled USR and RST. The RST switch is a hard-reset switch, and if you press it then it restarts the pyboard diff --git a/docs/reference/asm_thumb2_directives.rst b/docs/reference/asm_thumb2_directives.rst index 95acd7781fdd1..6e3ddaa16dfd8 100644 --- a/docs/reference/asm_thumb2_directives.rst +++ b/docs/reference/asm_thumb2_directives.rst @@ -1,4 +1,4 @@ -Assembler Directives +Assembler directives ==================== Labels diff --git a/docs/reference/asm_thumb2_float.rst b/docs/reference/asm_thumb2_float.rst index 46560413c9541..4672c4b275041 100644 --- a/docs/reference/asm_thumb2_float.rst +++ b/docs/reference/asm_thumb2_float.rst @@ -1,5 +1,5 @@ -Floating Point instructions -============================== +Floating point instructions +=========================== These instructions support the use of the ARM floating point coprocessor (on platforms such as the Pyboard which are equipped with one). The FPU @@ -61,7 +61,7 @@ Where ``[Rn + offset]`` denotes the memory address obtained by adding Rn to the is specified in bytes. Since each float value occupies a 32 bit word, when accessing arrays of floats the offset must always be a multiple of four bytes. -Data Comparison +Data comparison --------------- * vcmp(Sd, Sm) diff --git a/docs/reference/asm_thumb2_index.rst b/docs/reference/asm_thumb2_index.rst index f066e6acec500..ccf0201489a5e 100644 --- a/docs/reference/asm_thumb2_index.rst +++ b/docs/reference/asm_thumb2_index.rst @@ -1,6 +1,6 @@ .. _asm_thumb2_index: -Inline Assembler for Thumb2 architectures +Inline assembler for Thumb2 architectures ========================================= This document assumes some familiarity with assembly language programming and should be read after studying @@ -25,7 +25,7 @@ This enables the effect of instructions to be demonstrated in Python. In certain because Python doesn't support concepts such as indirection. The pseudocode employed in such cases is described on the relevant page. -Instruction Categories +Instruction categories ---------------------- The following sections details the subset of the ARM Thumb-2 instruction set supported by MicroPython. diff --git a/docs/reference/asm_thumb2_logical_bit.rst b/docs/reference/asm_thumb2_logical_bit.rst index 8c51feaf45f95..c57bfa8470f81 100644 --- a/docs/reference/asm_thumb2_logical_bit.rst +++ b/docs/reference/asm_thumb2_logical_bit.rst @@ -1,4 +1,4 @@ -Logical & Bitwise instructions +Logical & bitwise instructions ============================== Document conventions diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst index edac0ae681bba..9c68bab9a13e0 100644 --- a/docs/reference/constrained.rst +++ b/docs/reference/constrained.rst @@ -1,6 +1,6 @@ .. _constrained: -MicroPython on Microcontrollers +MicroPython on microcontrollers =============================== MicroPython is designed to be capable of running on microcontrollers. These @@ -12,7 +12,7 @@ based on a variety of architectures, the methods presented are generic: in some cases it will be necessary to obtain detailed information from platform specific documentation. -Flash Memory +Flash memory ------------ On the Pyboard the simple way to address the limited capacity is to fit a micro @@ -58,7 +58,7 @@ heap fragmentation. In general terms it is best to minimise the repeated creation and destruction of objects. The reason for this is covered in the section covering the `heap`_. -Compilation Phase +Compilation phase ~~~~~~~~~~~~~~~~~ When a module is imported, MicroPython compiles the code to bytecode which is @@ -85,7 +85,7 @@ imported in the usual way. Alternatively some or all modules may be implemented as frozen bytecode: on most platforms this saves even more RAM as the bytecode is run directly from flash rather than being stored in RAM. -Execution Phase +Execution phase ~~~~~~~~~~~~~~~ There are a number of coding techniques for reducing RAM usage. @@ -292,7 +292,7 @@ The Q(xxx) lines should be gone. .. _heap: -The Heap +The heap -------- When a running program instantiates an object the necessary RAM is allocated @@ -391,7 +391,7 @@ Symbol Meaning Each letter represents a single block of memory, a block being 16 bytes. So each line of the heap dump represents 0x400 bytes or 1KiB of RAM. -Control of Garbage Collection +Control of garbage collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A GC can be demanded at any time by issuing `gc.collect()`. It is advantageous @@ -420,7 +420,7 @@ initialisation the compiler may be starved of RAM when subsequent modules are imported. If modules do instantiate data on import then `gc.collect()` issued after the import will ameliorate the problem. -String Operations +String operations ----------------- MicroPython handles strings in an efficient manner and understanding this can diff --git a/docs/reference/index.rst b/docs/reference/index.rst index ed50bf0bf47cd..8cd5f03df48fc 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -1,5 +1,5 @@ -The MicroPython language -======================== +MicroPython language and implementation +======================================= MicroPython aims to implement the Python 3.4 standard (with selected features from later versions) with respect to language syntax, and most diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst index dfdee048c1310..57690ac212c64 100644 --- a/docs/reference/isr_rules.rst +++ b/docs/reference/isr_rules.rst @@ -29,7 +29,7 @@ This summarises the points detailed below and lists the principal recommendation * Allocate an emergency exception buffer (see below). -MicroPython Issues +MicroPython issues ------------------ The emergency exception buffer @@ -214,7 +214,7 @@ Exceptions If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the exception is handled by the ISR code. -General Issues +General issues -------------- This is merely a brief introduction to the subject of real time programming. Beginners should note @@ -225,7 +225,7 @@ with an appreciation of the following issues. .. _ISR: -Interrupt Handler Design +Interrupt handler design ~~~~~~~~~~~~~~~~~~~~~~~~ As mentioned above, ISR's should be designed to be as simple as possible. They should always return in a short, @@ -276,7 +276,7 @@ advanced topic beyond the scope of this tutorial. .. _Critical: -Critical Sections +Critical sections ~~~~~~~~~~~~~~~~~ An example of a critical section of code is one which accesses more than one variable which can be affected by an ISR. If diff --git a/docs/reference/repl.rst b/docs/reference/repl.rst index 0c6f04b7c5090..06ba918117f33 100644 --- a/docs/reference/repl.rst +++ b/docs/reference/repl.rst @@ -103,7 +103,7 @@ For example: KeyboardInterrupt: >>> -Paste Mode +Paste mode ---------- If you want to paste some code into your terminal window, the auto-indent feature @@ -143,7 +143,7 @@ the auto-indent feature, and changes the prompt from ``>>>`` to ``===``. For exa Paste Mode allows blank lines to be pasted. The pasted text is compiled as if it were a file. Pressing Ctrl-D exits paste mode and initiates the compilation. -Soft Reset +Soft reset ---------- A soft reset will reset the python interpreter, but tries not to reset the @@ -196,7 +196,7 @@ So you can use the underscore to save the result in a variable. For example: 15 >>> -Raw Mode +Raw mode -------- Raw mode is not something that a person would normally use. It is intended for diff --git a/docs/reference/speed_python.rst b/docs/reference/speed_python.rst index a6951ed334856..aa9777859242f 100644 --- a/docs/reference/speed_python.rst +++ b/docs/reference/speed_python.rst @@ -1,6 +1,6 @@ .. _speed_python: -Maximising MicroPython Speed +Maximising MicroPython speed ============================ .. contents:: @@ -40,7 +40,7 @@ the best algorithm is employed. This is a topic for textbooks rather than for a MicroPython guide but spectacular performance gains can sometimes be achieved by adopting algorithms known for their efficiency. -RAM Allocation +RAM allocation ~~~~~~~~~~~~~~ To design efficient MicroPython code it is necessary to have an understanding of the @@ -69,7 +69,7 @@ example, objects which support stream interface (e.g., file or UART) provide ``r method which allocates new buffer for read data, but also a ``readinto()`` method to read data into an existing buffer. -Floating Point +Floating point ~~~~~~~~~~~~~~ Some MicroPython ports allocate floating point numbers on heap. Some other ports From 1bc9fc80821edea293bc04a4c1c2c462dc546813 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 2 Jan 2020 09:40:54 -0600 Subject: [PATCH 0854/1299] tests/run-tests: Handle 'CRASH' return by float.py feature test. It is possile for `run_feature_check(pyb, args, base_path, 'float.py')` to return `b'CRASH'`. This causes an unhandled exception in `int()`. This commit fixes the problem by first testing for `b'CRASH'` before trying to convert the return value to an integer. --- tests/run-tests | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/run-tests b/tests/run-tests index 789a6f06c0b77..b02463dc379a8 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -288,7 +288,11 @@ def run_tests(pyb, tests, args, base_path="."): skip_tests.add('cmdline/repl_emacs_keys.py') upy_byteorder = run_feature_check(pyb, args, base_path, 'byteorder.py') - upy_float_precision = int(run_feature_check(pyb, args, base_path, 'float.py')) + upy_float_precision = run_feature_check(pyb, args, base_path, 'float.py') + if upy_float_precision == b'CRASH': + upy_float_precision = 0 + else: + upy_float_precision = int(upy_float_precision) has_complex = run_feature_check(pyb, args, base_path, 'complex.py') == b'complex\n' has_coverage = run_feature_check(pyb, args, base_path, 'coverage.py') == b'coverage\n' cpy_byteorder = subprocess.check_output([CPYTHON3, base_path + '/feature_check/byteorder.py']) From 99ed431d2840b30f67eae49be96d31c7faeca75e Mon Sep 17 00:00:00 2001 From: Jason Neal Date: Sat, 4 Jan 2020 23:00:27 +1300 Subject: [PATCH 0855/1299] docs/library/machine.I2C.rst: Use positional-only arguments syntax. Addresses issue #5196. --- docs/library/machine.I2C.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst index f589124378135..2cbfec1ba83bf 100644 --- a/docs/library/machine.I2C.rst +++ b/docs/library/machine.I2C.rst @@ -89,7 +89,7 @@ These methods are available on software I2C only. Generate a STOP condition on the bus (SDA transitions to high while SCL is high). -.. method:: I2C.readinto(buf, nack=True) +.. method:: I2C.readinto(buf, nack=True, /) Reads bytes from the bus and stores them into *buf*. The number of bytes read is the length of *buf*. An ACK will be sent on the bus after @@ -109,13 +109,13 @@ Standard bus operations The following methods implement the standard I2C master read and write operations that target a given slave device. -.. method:: I2C.readfrom(addr, nbytes, stop=True) +.. method:: I2C.readfrom(addr, nbytes, stop=True, /) Read *nbytes* from the slave specified by *addr*. If *stop* is true then a STOP condition is generated at the end of the transfer. Returns a `bytes` object with the data read. -.. method:: I2C.readfrom_into(addr, buf, stop=True) +.. method:: I2C.readfrom_into(addr, buf, stop=True, /) Read into *buf* from the slave specified by *addr*. The number of bytes read will be the length of *buf*. @@ -123,7 +123,7 @@ operations that target a given slave device. The method returns ``None``. -.. method:: I2C.writeto(addr, buf, stop=True) +.. method:: I2C.writeto(addr, buf, stop=True, /) Write the bytes from *buf* to the slave specified by *addr*. If a NACK is received following the write of a byte from *buf* then the @@ -131,7 +131,7 @@ operations that target a given slave device. generated at the end of the transfer, even if a NACK is received. The function returns the number of ACKs that were received. -.. method:: I2C.writevto(addr, vector, stop=True) +.. method:: I2C.writevto(addr, vector, stop=True, /) Write the bytes contained in *vector* to the slave specified by *addr*. *vector* should be a tuple or list of objects with the buffer protocol. From 5ef3b6b2d9aa60febe545d6f12a5d1b7300739ce Mon Sep 17 00:00:00 2001 From: Jason Neal Date: Sun, 5 Jan 2020 01:28:12 +1300 Subject: [PATCH 0856/1299] docs/library/machine.UART.rst: Detail timeout behaviour of read methods. Also document existence of "invert" argument to constructor. --- docs/library/machine.UART.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst index 5fcdc2758e0ff..70984dfb2fff1 100644 --- a/docs/library/machine.UART.rst +++ b/docs/library/machine.UART.rst @@ -58,6 +58,9 @@ Methods - *rx* specifies the RX pin to use. - *txbuf* specifies the length in characters of the TX buffer. - *rxbuf* specifies the length in characters of the RX buffer. + - *timeout* specifies the time to wait for the first character (in ms). + - *timeout_char* specifies the time to wait between characters (in ms). + - *invert* specifies which lines to invert. On the WiPy only the following keyword-only parameter is supported: @@ -87,7 +90,8 @@ Methods .. method:: UART.read([nbytes]) Read characters. If ``nbytes`` is specified then read at most that many bytes, - otherwise read as much data as possible. + otherwise read as much data as possible. It may return sooner if a timeout + is reached. The timeout is configurable in the constructor. Return value: a bytes object containing the bytes read in. Returns ``None`` on timeout. @@ -95,14 +99,16 @@ Methods .. method:: UART.readinto(buf[, nbytes]) Read bytes into the ``buf``. If ``nbytes`` is specified then read at most - that many bytes. Otherwise, read at most ``len(buf)`` bytes. + that many bytes. Otherwise, read at most ``len(buf)`` bytes. It may return sooner if a timeout + is reached. The timeout is configurable in the constructor. Return value: number of bytes read and stored into ``buf`` or ``None`` on timeout. .. method:: UART.readline() - Read a line, ending in a newline character. + Read a line, ending in a newline character. It may return sooner if a timeout + is reached. The timeout is configurable in the constructor. Return value: the line read or ``None`` on timeout. From 99b8c1a93731771bd7d8801a8ea939922f3d2991 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 6 Jan 2020 23:03:22 +1100 Subject: [PATCH 0857/1299] esp32/Makefile: Assign result of $call to dummy var for older make. Make version 4.1 and lower does not allow $call as the main expression on a line, so assign the result of the $call to a dummy variable. Fixes issue #5426. --- ports/esp32/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index ecaa3e62acd3b..a9002b651217e 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -67,7 +67,7 @@ ESPIDF = $(IDF_PATH) else $(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) $(info See README.md for installation instructions.) -$(call print_supported_git_hash) +dummy := $(call print_supported_git_hash) $(error ESPIDF not set) endif endif @@ -99,7 +99,7 @@ $(info The git hash of ESP IDF does not match the supported version) $(info The build may complete and the firmware may work but it is not guaranteed) $(info ESP IDF path: $(ESPIDF)) $(info Current git hash: $(ESPIDF_CURHASH)) -$(call print_supported_git_hash) +dummy := $(call print_supported_git_hash) endif # pretty format of ESP IDF version, used internally by the IDF From 4d528bbaa836b3d6ec0218ca7f7c92e1bf73704c Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 6 Jan 2020 23:26:00 +1100 Subject: [PATCH 0858/1299] tests/cpydiff: Add CPy diff-test for using dict.keys() as a set. See issue #5493. --- tests/cpydiff/types_dict_keys_set.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/cpydiff/types_dict_keys_set.py diff --git a/tests/cpydiff/types_dict_keys_set.py b/tests/cpydiff/types_dict_keys_set.py new file mode 100644 index 0000000000000..1a9af9d389b1c --- /dev/null +++ b/tests/cpydiff/types_dict_keys_set.py @@ -0,0 +1,7 @@ +""" +categories: Types,dict +description: Dictionary keys view does not behave as a set. +cause: Not implemented. +workaround: Explicitly convert keys to a set before using set operations. +""" +print({1:2, 3:4}.keys() & {1}) From 54a2584de10103ba3e559de1034cc76962ec681e Mon Sep 17 00:00:00 2001 From: stijn Date: Tue, 7 Jan 2020 01:36:09 +1400 Subject: [PATCH 0859/1299] tests/unix: Make unix time test pass on more platforms. As the mktime documentation for CPython states: "The earliest date for which it can generate a time is platform-dependent". In particular on Windows this depends on the timezone so e.g. for UTC+2 the earliest is 2 hours past midnight January 1970. So change the reference to the earliest possible, for UTC+14. --- tests/unix/time.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unix/time.py b/tests/unix/time.py index a96c3f5b66aa7..35eddbe0954c1 100644 --- a/tests/unix/time.py +++ b/tests/unix/time.py @@ -5,7 +5,7 @@ DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] -tzseconds = -time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0)) +tzseconds = -time.mktime((1970, 1, 1, 14, 0, 0, 0, 0, 0)) def is_leap(year): return (year % 4) == 0 @@ -22,7 +22,7 @@ def test(): else: DAYS_PER_MONTH[2] = 28 for day in range(1, DAYS_PER_MONTH[month] + 1): - secs = time.mktime((year, month, day, 0, 0, 0, 0, 0, 0)) + tzseconds + secs = time.mktime((year, month, day, 14, 0, 0, 0, 0, 0)) + tzseconds if secs != seconds: print("mktime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds)) return From e3187b052f14872fdb5e2d2338d359013a544fae Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 7 Jan 2020 23:59:29 +1100 Subject: [PATCH 0860/1299] stm32/boards/PYBD: Change RTC asynch prediv from 1 to 4. This change has the following effects: - Reduces the resolution of the RTC sub-second counter from 30.52us to 122.07us. - Allows RTC.calibration() to now support positive values (as well as negative values). - Reduces VBAT current consumption in standby mode by a small amount. For general purpose use 122us resolution of the sub-second counter is good enough, and the benefits of full range calibration and minor reduction in VBAT consumption are worth the change. --- ports/stm32/boards/PYBD_SF2/mpconfigboard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h index 4ce17abd870c1..757dacf9a7c18 100644 --- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h +++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h @@ -56,8 +56,8 @@ void board_sleep(int value); #define MICROPY_HW_FLASH_LATENCY (FLASH_LATENCY_3) // There is an external 32kHz oscillator -#define RTC_ASYNCH_PREDIV (0) -#define RTC_SYNCH_PREDIV (0x7fff) +#define RTC_ASYNCH_PREDIV (3) +#define RTC_SYNCH_PREDIV (0x1fff) #define MICROPY_HW_RTC_USE_BYPASS (1) #define MICROPY_HW_RTC_USE_US (1) #define MICROPY_HW_RTC_USE_CALOUT (1) From bfbd94401d9cf658fc50b2e45896aba300a7af71 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 Jan 2020 11:01:14 +1100 Subject: [PATCH 0861/1299] py: Make mp_obj_get_type() return a const ptr to mp_obj_type_t. Most types are in rodata/ROM, and mp_obj_base_t.type is a constant pointer, so enforce this const-ness throughout the code base. If a type ever needs to be modified (eg a user type) then a simple cast can be used. --- extmod/modujson.c | 2 +- ports/stm32/moduos.c | 2 +- ports/stm32/usb.c | 2 +- py/builtinhelp.c | 2 +- py/nativeglue.h | 2 +- py/obj.c | 24 ++++++++++++------------ py/obj.h | 2 +- py/objfun.c | 2 +- py/objstr.c | 6 +++--- py/objstrunicode.c | 2 +- py/objtuple.c | 2 +- py/objtype.c | 6 +++--- py/opmethods.c | 8 ++++---- py/runtime.c | 18 +++++++++--------- py/sequence.c | 2 +- py/stream.c | 2 +- 16 files changed, 42 insertions(+), 42 deletions(-) diff --git a/extmod/modujson.c b/extmod/modujson.c index 15ed2f38d828b..b7c5121cddcfa 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.c @@ -96,7 +96,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { stack.len = 0; stack.items = NULL; mp_obj_t stack_top = MP_OBJ_NULL; - mp_obj_type_t *stack_top_type = NULL; + const mp_obj_type_t *stack_top_type = NULL; mp_obj_t stack_key = MP_OBJ_NULL; S_NEXT(s); for (;;) { diff --git a/ports/stm32/moduos.c b/ports/stm32/moduos.c index 8bf58623c93d3..cafe2fe32661a 100644 --- a/ports/stm32/moduos.c +++ b/ports/stm32/moduos.c @@ -111,7 +111,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); #endif bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream) { - mp_obj_type_t *type = mp_obj_get_type(stream); + const mp_obj_type_t *type = mp_obj_get_type(stream); return type == &pyb_uart_type #if MICROPY_HW_ENABLE_USB || type == &pyb_usb_vcp_type diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8a4b7485bb794..432d55a31ed48 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -533,7 +533,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * mp_raise_ValueError("too many logical units"); } for (size_t i = 0; i < msc_n; ++i) { - mp_obj_type_t *type = mp_obj_get_type(items[i]); + const mp_obj_type_t *type = mp_obj_get_type(items[i]); if (type == &pyb_flash_type #if MICROPY_HW_ENABLE_SDCARD || type == &pyb_sdcard_type diff --git a/py/builtinhelp.c b/py/builtinhelp.c index 8f162d8858314..033242b3df5a5 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -134,7 +134,7 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) { } #endif - mp_obj_type_t *type = mp_obj_get_type(obj); + const mp_obj_type_t *type = mp_obj_get_type(obj); // try to print something sensible about the given object mp_print_str(MP_PYTHON_PRINTER, "object "); diff --git a/py/nativeglue.h b/py/nativeglue.h index 021e7a8ecb7ea..1b6d9cc7a069a 100644 --- a/py/nativeglue.h +++ b/py/nativeglue.h @@ -146,7 +146,7 @@ typedef struct _mp_fun_table_t { NORETURN // Only certain compilers support no-return attributes in function pointer declarations #endif void (*raise_msg)(const mp_obj_type_t *exc_type, const char *msg); - mp_obj_type_t *(*obj_get_type)(mp_const_obj_t o_in); + const mp_obj_type_t *(*obj_get_type)(mp_const_obj_t o_in); mp_obj_t (*obj_new_str)(const char* data, size_t len); mp_obj_t (*obj_new_bytes)(const byte* data, size_t len); mp_obj_t (*obj_new_bytearray_by_ref)(size_t n, void *items); diff --git a/py/obj.c b/py/obj.c index 4588d896a5200..f2a884754340e 100644 --- a/py/obj.c +++ b/py/obj.c @@ -37,18 +37,18 @@ #include "py/stackctrl.h" #include "py/stream.h" // for mp_obj_print -mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { +const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { if (mp_obj_is_small_int(o_in)) { - return (mp_obj_type_t*)&mp_type_int; + return &mp_type_int; } else if (mp_obj_is_qstr(o_in)) { - return (mp_obj_type_t*)&mp_type_str; + return &mp_type_str; #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(o_in)) { - return (mp_obj_type_t*)&mp_type_float; + return &mp_type_float; #endif } else { const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in); - return (mp_obj_type_t*)o->type; + return o->type; } } @@ -65,7 +65,7 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t return; } #endif - mp_obj_type_t *type = mp_obj_get_type(o_in); + const mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->print != NULL) { type->print((mp_print_t*)print, o_in, kind); } else { @@ -119,7 +119,7 @@ bool mp_obj_is_true(mp_obj_t arg) { return 1; } } else { - mp_obj_type_t *type = mp_obj_get_type(arg); + const mp_obj_type_t *type = mp_obj_get_type(arg); if (type->unary_op != NULL) { mp_obj_t result = type->unary_op(MP_UNARY_OP_BOOL, arg); if (result != MP_OBJ_NULL) { @@ -139,7 +139,7 @@ bool mp_obj_is_true(mp_obj_t arg) { } bool mp_obj_is_callable(mp_obj_t o_in) { - mp_call_fun_t call = mp_obj_get_type(o_in)->call; + const mp_call_fun_t call = mp_obj_get_type(o_in)->call; if (call != mp_obj_instance_call) { return call != NULL; } @@ -209,7 +209,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { } // generic type, call binary_op(MP_BINARY_OP_EQUAL) - mp_obj_type_t *type = mp_obj_get_type(o1); + const mp_obj_type_t *type = mp_obj_get_type(o1); if (type->binary_op != NULL) { mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { @@ -451,7 +451,7 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { GET_STR_LEN(o_in, l); return MP_OBJ_NEW_SMALL_INT(l); } else { - mp_obj_type_t *type = mp_obj_get_type(o_in); + const mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->unary_op != NULL) { return type->unary_op(MP_UNARY_OP_LEN, o_in); } else { @@ -461,7 +461,7 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { } mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { - mp_obj_type_t *type = mp_obj_get_type(base); + const mp_obj_type_t *type = mp_obj_get_type(base); if (type->subscr != NULL) { mp_obj_t ret = type->subscr(base, index, value); if (ret != MP_OBJ_NULL) { @@ -506,7 +506,7 @@ mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) { } bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { - mp_obj_type_t *type = mp_obj_get_type(obj); + const mp_obj_type_t *type = mp_obj_get_type(obj); if (type->buffer_p.get_buffer == NULL) { return false; } diff --git a/py/obj.h b/py/obj.h index f1444749177b9..d98a0470dac62 100644 --- a/py/obj.h +++ b/py/obj.h @@ -669,7 +669,7 @@ mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf); mp_obj_t mp_obj_new_module(qstr module_name); mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items); -mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); +const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); const char *mp_obj_get_type_str(mp_const_obj_t o_in); bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type); diff --git a/py/objfun.c b/py/objfun.c index 7051f3476d456..984d2000a81d6 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -455,7 +455,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { size_t l; return (mp_uint_t)mp_obj_str_get_data(obj, &l); } else { - mp_obj_type_t *type = mp_obj_get_type(obj); + const mp_obj_type_t *type = mp_obj_get_type(obj); #if MICROPY_PY_BUILTINS_FLOAT if (type == &mp_type_float) { // convert float to int (could also pass in float registers) diff --git a/py/objstr.c b/py/objstr.c index 822c9fc418337..454d1cbcc5445 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -320,7 +320,7 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i } // from now on we need lhs type and data, so extract them - mp_obj_type_t *lhs_type = mp_obj_get_type(lhs_in); + const mp_obj_type_t *lhs_type = mp_obj_get_type(lhs_in); GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len); // check for multiply @@ -420,7 +420,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s // This is used for both bytes and 8-bit strings. This is not used for unicode strings. STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { - mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self_in); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { // load @@ -1743,7 +1743,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count); #if MICROPY_PY_BUILTINS_STR_PARTITION STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { mp_check_self(mp_obj_is_str_or_bytes(self_in)); - mp_obj_type_t *self_type = mp_obj_get_type(self_in); + const mp_obj_type_t *self_type = mp_obj_get_type(self_in); if (self_type != mp_obj_get_type(arg)) { bad_implicit_conversion(arg); } diff --git a/py/objstrunicode.c b/py/objstrunicode.c index 5a127243bc089..e5a57ab942524 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -176,7 +176,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s } STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { - mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self_in); assert(type == &mp_type_str); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { diff --git a/py/objtuple.c b/py/objtuple.c index 740e0795b3328..10a5e586f6c36 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -105,7 +105,7 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg // Don't pass MP_BINARY_OP_NOT_EQUAL here STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { mp_check_self(mp_obj_is_tuple_compatible(self_in)); - mp_obj_type_t *another_type = mp_obj_get_type(another_in); + const mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); if (another_type->getiter != mp_obj_tuple_getiter) { // Slow path for user subclasses diff --git a/py/objtype.c b/py/objtype.c index 5d4dd7d2ffec2..2ea3f1c18728c 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -897,7 +897,7 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) if (member[0] == MP_OBJ_NULL) { return MP_OBJ_NULL; } else if (member[0] == MP_OBJ_SENTINEL) { - mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); + const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); if (iter_buf == NULL) { iter_buf = m_new_obj(mp_obj_iter_buf_t); } @@ -919,7 +919,7 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, }; mp_obj_class_lookup(&lookup, self->base.type); if (member[0] == MP_OBJ_SENTINEL) { - mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); + const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]); return type->buffer_p.get_buffer(self->subobj[0], bufinfo, flags); } else { return 1; // object does not support buffer protocol @@ -1393,7 +1393,7 @@ STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) { MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance); mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type) { - mp_obj_type_t *self_type = mp_obj_get_type(self_in); + const mp_obj_type_t *self_type = mp_obj_get_type(self_in); if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self_type), native_type)) { return MP_OBJ_NULL; } diff --git a/py/opmethods.c b/py/opmethods.c index 247fa5bbc8f8b..595cc088ba933 100644 --- a/py/opmethods.c +++ b/py/opmethods.c @@ -28,25 +28,25 @@ #include "py/builtin.h" STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { - mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self_in); return type->subscr(self_in, key_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { - mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self_in); return type->subscr(self_in, key_in, value_in); } MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem); STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { - mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self_in); return type->subscr(self_in, key_in, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem); STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { - mp_obj_type_t *type = mp_obj_get_type(lhs_in); + const mp_obj_type_t *type = mp_obj_get_type(lhs_in); return type->binary_op(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains); diff --git a/py/runtime.c b/py/runtime.c index d5511236d4412..26b473bbe9121 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -276,7 +276,7 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { } return MP_OBJ_NEW_SMALL_INT(h); } else { - mp_obj_type_t *type = mp_obj_get_type(arg); + const mp_obj_type_t *type = mp_obj_get_type(arg); if (type->unary_op != NULL) { mp_obj_t result = type->unary_op(op, arg); if (result != MP_OBJ_NULL) { @@ -560,7 +560,7 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } // generic binary_op supplied by type - mp_obj_type_t *type; + const mp_obj_type_t *type; generic_binary_op: type = mp_obj_get_type(lhs); if (type->binary_op != NULL) { @@ -636,7 +636,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, cons DEBUG_OP_printf("calling function %p(n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", fun_in, n_args, n_kw, args); // get the type - mp_obj_type_t *type = mp_obj_get_type(fun_in); + const mp_obj_type_t *type = mp_obj_get_type(fun_in); // do the call if (type->call != NULL) { @@ -1067,7 +1067,7 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) { dest[1] = MP_OBJ_NULL; // get the type - mp_obj_type_t *type = mp_obj_get_type(obj); + const mp_obj_type_t *type = mp_obj_get_type(obj); // look for built-in names #if MICROPY_CPYTHON_COMPAT @@ -1138,7 +1138,7 @@ void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catc void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value); - mp_obj_type_t *type = mp_obj_get_type(base); + const mp_obj_type_t *type = mp_obj_get_type(base); if (type->attr != NULL) { mp_obj_t dest[2] = {MP_OBJ_SENTINEL, value}; type->attr(base, attr, dest); @@ -1158,7 +1158,7 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { assert(o_in); - mp_obj_type_t *type = mp_obj_get_type(o_in); + const mp_obj_type_t *type = mp_obj_get_type(o_in); // Check for native getiter which is the identity. We handle this case explicitly // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used. @@ -1203,7 +1203,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration() // may also raise StopIteration() mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { - mp_obj_type_t *type = mp_obj_get_type(o_in); + const mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->iternext != NULL) { return type->iternext(o_in); } else { @@ -1228,7 +1228,7 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { // may raise other exceptions mp_obj_t mp_iternext(mp_obj_t o_in) { MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext - mp_obj_type_t *type = mp_obj_get_type(o_in); + const mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->iternext != NULL) { return type->iternext(o_in); } else { @@ -1263,7 +1263,7 @@ mp_obj_t mp_iternext(mp_obj_t o_in) { // TODO: Unclear what to do with StopIterarion exception here. mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { assert((send_value != MP_OBJ_NULL) ^ (throw_value != MP_OBJ_NULL)); - mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self_in); if (type == &mp_type_gen_instance) { return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val); diff --git a/py/sequence.c b/py/sequence.c index 15e925000a17b..94a9bb9d5f4af 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -183,7 +183,7 @@ bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp // Special-case of index() which searches for mp_obj_t mp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args) { - mp_obj_type_t *type = mp_obj_get_type(args[0]); + const mp_obj_type_t *type = mp_obj_get_type(args[0]); mp_obj_t value = args[1]; size_t start = 0; size_t stop = len; diff --git a/py/stream.c b/py/stream.c index 762cd0fc08cf1..d795681cbcdbb 100644 --- a/py/stream.c +++ b/py/stream.c @@ -85,7 +85,7 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { - mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_obj_type_t *type = mp_obj_get_type(self_in); const mp_stream_p_t *stream_p = type->protocol; if (stream_p == NULL || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) From 7d2ccd027fce61642a3a1177220d7f9c69f371f9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 23 Oct 2019 11:56:37 +1100 Subject: [PATCH 0862/1299] py/mkenv.mk: Move usage of 32-bit flags to py.mk. This allows ports/variants to configure MICROPY_FORCE_32BIT after including mkenv.mk, but before py.mk. --- py/mkenv.mk | 5 ----- py/py.mk | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/py/mkenv.mk b/py/mkenv.mk index 3efeb181648f0..371d32046227d 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -55,11 +55,6 @@ OBJCOPY = $(CROSS_COMPILE)objcopy SIZE = $(CROSS_COMPILE)size STRIP = $(CROSS_COMPILE)strip AR = $(CROSS_COMPILE)ar -ifeq ($(MICROPY_FORCE_32BIT),1) -CC += -m32 -CXX += -m32 -LD += -m32 -endif MAKE_MANIFEST = $(PYTHON) $(TOP)/tools/makemanifest.py MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py diff --git a/py/py.mk b/py/py.mk index 8c2d3c7b80cc6..09de1962d3594 100644 --- a/py/py.mk +++ b/py/py.mk @@ -21,6 +21,13 @@ QSTR_GLOBAL_REQUIREMENTS += $(HEADER_BUILD)/mpversion.h # some code is performance bottleneck and compiled with other optimization options CSUPEROPT = -O3 +# Enable building 32-bit code on 64-bit host. +ifeq ($(MICROPY_FORCE_32BIT),1) +CC += -m32 +CXX += -m32 +LD += -m32 +endif + # External modules written in C. ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate From bd2fff66875ed5adab8ce163a7f2bdafbd0332f9 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 23 Oct 2019 11:20:07 +1100 Subject: [PATCH 0863/1299] unix: Add build variants, analogous to boards on bare-metal. Invoking "make" will still build the standard "micropython" executable, but other variants are now build using, eg, "make VARIANT=minimal". This follows how bare-metal ports specify a particular board, and allows running any make target (eg clean, test) with any variant. Convenience targets (eg "make coverage") are provided to retain the old behaviour, at least for now. See issue #3043. --- ports/unix/Makefile | 107 +++++++----------- ports/unix/mpconfigport.h | 16 ++- .../coverage/mpconfigvariant.h} | 6 +- .../unix/variants/coverage/mpconfigvariant.mk | 17 +++ .../fast/mpconfigvariant.h} | 3 +- ports/unix/variants/fast/mpconfigvariant.mk | 7 ++ .../freedos/mpconfigvariant.h} | 6 +- .../unix/variants/freedos/mpconfigvariant.mk | 20 ++++ .../minimal/mpconfigvariant.h} | 3 + .../unix/variants/minimal/mpconfigvariant.mk | 14 +++ .../nanbox/mpconfigvariant.h} | 6 +- ports/unix/variants/nanbox/mpconfigvariant.mk | 4 + .../unix/variants/standard/mpconfigvariant.h | 26 +++++ .../unix/variants/standard/mpconfigvariant.mk | 16 +++ 14 files changed, 173 insertions(+), 78 deletions(-) rename ports/unix/{mpconfigport_coverage.h => variants/coverage/mpconfigvariant.h} (94%) create mode 100644 ports/unix/variants/coverage/mpconfigvariant.mk rename ports/unix/{mpconfigport_fast.h => variants/fast/mpconfigvariant.h} (97%) create mode 100644 ports/unix/variants/fast/mpconfigvariant.mk rename ports/unix/{mpconfigport_freedos.h => variants/freedos/mpconfigvariant.h} (94%) create mode 100644 ports/unix/variants/freedos/mpconfigvariant.mk rename ports/unix/{mpconfigport_minimal.h => variants/minimal/mpconfigvariant.h} (98%) create mode 100644 ports/unix/variants/minimal/mpconfigvariant.mk rename ports/unix/{mpconfigport_nanbox.h => variants/nanbox/mpconfigvariant.h} (90%) create mode 100644 ports/unix/variants/nanbox/mpconfigvariant.mk create mode 100644 ports/unix/variants/standard/mpconfigvariant.h create mode 100644 ports/unix/variants/standard/mpconfigvariant.mk diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 2fa1373e73912..567b1d5c22c2c 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -1,16 +1,29 @@ --include mpconfigport.mk +# Select the variant to build for. +VARIANT ?= standard + +# If the build directory is not given, make it reflect the variant name. +BUILD ?= build-$(VARIANT) + +VARIANT_DIR ?= variants/$(VARIANT) +ifeq ($(wildcard $(VARIANT_DIR)/.),) +$(error Invalid VARIANT specified: $(VARIANT_DIR)) +endif + include ../../py/mkenv.mk +-include mpconfigport.mk +include $(VARIANT_DIR)/mpconfigvariant.mk # use FROZEN_MANIFEST for new projects, others are legacy FROZEN_MANIFEST ?= manifest.py FROZEN_DIR = FROZEN_MPY_DIR = -# define main target -PROG = micropython +# This should be configured by the mpconfigvariant.mk +PROG ?= micropython # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h +QSTR_GLOBAL_DEPENDENCIES = $(VARIANT_DIR)/mpconfigvariant.h # OS name, for simple autoconfig UNAME_S := $(shell uname -s) @@ -27,7 +40,7 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror CWARN += -Wpointer-arith -Wuninitialized -CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) +CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG @@ -156,7 +169,8 @@ SRC_C = \ alloc.c \ coverage.c \ fatfs_port.c \ - $(SRC_MOD) + $(SRC_MOD) \ + $(wildcard $(VARIANT_DIR)/*.c) LIB_SRC_C = $(addprefix lib/,\ $(LIB_SRC_C_EXTRA) \ @@ -188,83 +202,42 @@ endif include $(TOP)/py/mkrules.mk -.PHONY: test +.PHONY: test test_full test: $(PROG) $(TOP)/tests/run-tests $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests -# install micropython in /usr/local/bin -TARGET = micropython -PREFIX = $(DESTDIR)/usr/local -BINDIR = $(PREFIX)/bin - -install: micropython - install -d $(BINDIR) - install $(TARGET) $(BINDIR)/$(TARGET) +test_full: $(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 -d thread + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests --emit native + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests --via-mpy -d basics float micropython + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests --via-mpy --emit native -d basics float micropython + cat $(TOP)/tests/basics/0prelim.py | ./$(PROG) | grep -q 'abc' -# uninstall micropython -uninstall: - -rm $(BINDIR)/$(TARGET) +test_gcov: test_full + gcov -o $(BUILD)/py $(TOP)/py/*.c + gcov -o $(BUILD)/extmod $(TOP)/extmod/*.c -# build synthetically fast interpreter for benchmarking +# Maintain historical targets from pre-variant configurations. fast: - $(MAKE) COPT="-O2 -DNDEBUG -fno-crossjumping" CFLAGS_EXTRA='-DMP_CONFIGFILE=""' BUILD=build-fast PROG=micropython_fast FROZEN_MANIFEST= + $(MAKE) VARIANT=fast -# build a minimal interpreter minimal: - $(MAKE) COPT="-Os -DNDEBUG" CFLAGS_EXTRA='-DMP_CONFIGFILE=""' \ - BUILD=build-minimal PROG=micropython_minimal FROZEN_MANIFEST= \ - MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_SOCKET=0 MICROPY_PY_THREAD=0 \ - MICROPY_PY_TERMIOS=0 MICROPY_PY_USSL=0 \ - MICROPY_USE_READLINE=0 + $(MAKE) VARIANT=minimal -# build interpreter with nan-boxing as object model nanbox: - $(MAKE) \ - CFLAGS_EXTRA='-DMP_CONFIGFILE=""' \ - BUILD=build-nanbox \ - PROG=micropython_nanbox \ - MICROPY_FORCE_32BIT=1 + $(MAKE) VARIANT=nanbox freedos: - $(MAKE) \ - CC=i586-pc-msdosdjgpp-gcc \ - STRIP=i586-pc-msdosdjgpp-strip \ - SIZE=i586-pc-msdosdjgpp-size \ - CFLAGS_EXTRA='-DMP_CONFIGFILE="" -DMICROPY_NLR_SETJMP -Dtgamma=gamma -DMICROPY_EMIT_X86=0 -DMICROPY_NO_ALLOCA=1 -DMICROPY_PY_USELECT_POSIX=0' \ - BUILD=build-freedos \ - PROG=micropython_freedos \ - MICROPY_PY_SOCKET=0 \ - MICROPY_PY_FFI=0 \ - MICROPY_PY_JNI=0 \ - MICROPY_PY_BTREE=0 \ - MICROPY_PY_THREAD=0 \ - MICROPY_PY_USSL=0 - -# build an interpreter for coverage testing and do the testing + $(MAKE) VARIANT=freedos + coverage: - $(MAKE) \ - COPT="-O0" CFLAGS_EXTRA='$(CFLAGS_EXTRA) -DMP_CONFIGFILE="" \ - -fprofile-arcs -ftest-coverage \ - -Wdouble-promotion -Wformat -Wmissing-declarations -Wmissing-prototypes -Wsign-compare \ - -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ - -DMICROPY_UNIX_COVERAGE' \ - LDFLAGS_EXTRA='-fprofile-arcs -ftest-coverage' \ - MICROPY_VFS_FAT=1 MICROPY_VFS_LFS1=1 MICROPY_VFS_LFS2=1 \ - FROZEN_MANIFEST=manifest_coverage.py \ - BUILD=build-coverage PROG=micropython_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 micropython - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/micropython_coverage ./run-tests --via-mpy --emit native -d basics float micropython - cat $(TOP)/tests/basics/0prelim.py | ./micropython_coverage | grep -q 'abc' - gcov -o build-coverage/py $(TOP)/py/*.c - gcov -o build-coverage/extmod $(TOP)/extmod/*.c + $(MAKE) VARIANT=coverage +coverage_test: + $(MAKE) VARIANT=coverage test_gcov # Value of configure's --host= option (required for cross-compilation). # Deduce it from CROSS_COMPILE by default, but can be overridden. diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index d633726a16a78..f435c3ff3c730 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -24,7 +24,15 @@ * THE SOFTWARE. */ -// options to control how MicroPython is built +// Options to control how MicroPython is built for this port, +// overriding defaults in py/mpconfig.h. + +// Variant-specific definitions. +#include "mpconfigvariant.h" + +// The minimal variant's config covers everything. +// If we're building the minimal variant, ignore the rest of this file. +#ifndef MICROPY_UNIX_MINIMAL #define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_PERSISTENT_CODE_LOAD (1) @@ -64,7 +72,9 @@ #define MICROPY_ENABLE_SOURCE_LINE (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#ifndef MICROPY_STREAMS_NON_BLOCK #define MICROPY_STREAMS_NON_BLOCK (1) +#endif #define MICROPY_STREAMS_POSIX_API (1) #define MICROPY_OPT_COMPUTED_GOTO (1) #ifndef MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE @@ -97,11 +107,13 @@ #define MICROPY_PERSISTENT_CODE_SAVE (1) #define MICROPY_COMP_CONST (0) #endif +#ifndef MICROPY_PY_SYS_PLATFORM #if defined(__APPLE__) && defined(__MACH__) #define MICROPY_PY_SYS_PLATFORM "darwin" #else #define MICROPY_PY_SYS_PLATFORM "linux" #endif +#endif #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_STDFILES (1) #define MICROPY_PY_SYS_EXC_INFO (1) @@ -331,3 +343,5 @@ void mp_unix_mark_exec(void); // For debugging purposes, make printf() available to any source file. #include #endif + +#endif // MICROPY_UNIX_MINIMAL diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/variants/coverage/mpconfigvariant.h similarity index 94% rename from ports/unix/mpconfigport_coverage.h rename to ports/unix/variants/coverage/mpconfigvariant.h index 8a0bf3be48609..f383a837005e3 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -24,14 +24,12 @@ * THE SOFTWARE. */ -// Default unix config while intended to be comprehensive, may still not enable -// all the features, this config should enable more (testable) options. +// This config enables almost all possible features such that it can be used +// for coverage testing. #define MICROPY_VFS (1) #define MICROPY_PY_UOS_VFS (1) -#include - #define MICROPY_OPT_MATH_FACTORIAL (1) #define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_ENABLE_SCHEDULER (1) diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk new file mode 100644 index 0000000000000..e55b22eb926b2 --- /dev/null +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -0,0 +1,17 @@ +PROG ?= micropython_coverage + +COPT = -O0 + +CFLAGS_EXTRA += \ + -fprofile-arcs -ftest-coverage \ + -Wdouble-promotion -Wformat -Wmissing-declarations -Wmissing-prototypes -Wsign-compare \ + -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ + -DMICROPY_UNIX_COVERAGE + +LDFLAGS_EXTRA += -fprofile-arcs -ftest-coverage + +FROZEN_MANIFEST = manifest_coverage.py + +MICROPY_VFS_FAT = 1 +MICROPY_VFS_LFS1 = 1 +MICROPY_VFS_LFS2 = 1 diff --git a/ports/unix/mpconfigport_fast.h b/ports/unix/variants/fast/mpconfigvariant.h similarity index 97% rename from ports/unix/mpconfigport_fast.h rename to ports/unix/variants/fast/mpconfigvariant.h index 193567a2949fd..6d73275fdebfc 100644 --- a/ports/unix/mpconfigport_fast.h +++ b/ports/unix/variants/fast/mpconfigvariant.h @@ -28,8 +28,9 @@ // synthetic benchmarking, at the expense of features supported and memory // usage. This config is not intended to be used in production. -#include #define MICROPY_PY___FILE__ (0) // 91 is a magic number proposed by @dpgeorge, which make pystone run ~ at tie // with CPython 3.4. #define MICROPY_MODULE_DICT_SIZE (91) + +#include "variants/DEV/mpconfigvariant.h" diff --git a/ports/unix/variants/fast/mpconfigvariant.mk b/ports/unix/variants/fast/mpconfigvariant.mk new file mode 100644 index 0000000000000..60c1d525d35dd --- /dev/null +++ b/ports/unix/variants/fast/mpconfigvariant.mk @@ -0,0 +1,7 @@ +# build synthetically fast interpreter for benchmarking + +COPT = "-O2 -DNDEBUG -fno-crossjumping" + +PROG = micropython_fast + +FROZEN_MANIFEST = diff --git a/ports/unix/mpconfigport_freedos.h b/ports/unix/variants/freedos/mpconfigvariant.h similarity index 94% rename from ports/unix/mpconfigport_freedos.h rename to ports/unix/variants/freedos/mpconfigvariant.h index 09c85ab1e3377..338b34492de7f 100644 --- a/ports/unix/mpconfigport_freedos.h +++ b/ports/unix/variants/freedos/mpconfigvariant.h @@ -26,15 +26,15 @@ // options to control how MicroPython is built -#include +#define MICROPY_PY_USELECT_POSIX (0) -#undef MICROPY_STREAMS_NON_BLOCK #define MICROPY_STREAMS_NON_BLOCK (0) -#undef MICROPY_PY_SYS_PLATFORM #define MICROPY_PY_SYS_PLATFORM "freedos" // djgpp dirent struct does not have d_ino field #undef _DIRENT_HAVE_D_INO #define MICROPY_USE_INTERNAL_ERRNO (1) + +#include "variants/DEV/mpconfigvariant.h" diff --git a/ports/unix/variants/freedos/mpconfigvariant.mk b/ports/unix/variants/freedos/mpconfigvariant.mk new file mode 100644 index 0000000000000..f1d0ac21b0a5f --- /dev/null +++ b/ports/unix/variants/freedos/mpconfigvariant.mk @@ -0,0 +1,20 @@ +CC = i586-pc-msdosdjgpp-gcc + +STRIP = i586-pc-msdosdjgpp-strip + +SIZE = i586-pc-msdosdjgpp-size + +CFLAGS_EXTRA = \ + -DMICROPY_NLR_SETJMP \ + -Dtgamma=gamma \ + -DMICROPY_EMIT_X86=0 \ + -DMICROPY_NO_ALLOCA=1 \ + +PROG = micropython_freedos + +MICROPY_PY_SOCKET = 0 +MICROPY_PY_FFI = 0 +MICROPY_PY_JNI = 0 +MICROPY_PY_BTREE = 0 +MICROPY_PY_THREAD = 0 +MICROPY_PY_USSL = 0 diff --git a/ports/unix/mpconfigport_minimal.h b/ports/unix/variants/minimal/mpconfigvariant.h similarity index 98% rename from ports/unix/mpconfigport_minimal.h rename to ports/unix/variants/minimal/mpconfigvariant.h index c49819e742aef..e961ff4b247d9 100644 --- a/ports/unix/mpconfigport_minimal.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -26,6 +26,9 @@ // options to control how MicroPython is built +// Prevent the rest of the default mpconfigport.h being used. +#define MICROPY_UNIX_MINIMAL (1) + #define MICROPY_ALLOC_QSTR_CHUNK_INIT (64) #define MICROPY_ALLOC_PARSE_RULE_INIT (8) #define MICROPY_ALLOC_PARSE_RULE_INC (8) diff --git a/ports/unix/variants/minimal/mpconfigvariant.mk b/ports/unix/variants/minimal/mpconfigvariant.mk new file mode 100644 index 0000000000000..19f8ad64a341a --- /dev/null +++ b/ports/unix/variants/minimal/mpconfigvariant.mk @@ -0,0 +1,14 @@ +# build a minimal interpreter +COPT = -Os -DNDEBUG + +PROG = micropython_minimal + +FROZEN_MANIFEST = + +MICROPY_PY_BTREE = 0 +MICROPY_PY_FFI = 0 +MICROPY_PY_SOCKET = 0 +MICROPY_PY_THREAD = 0 +MICROPY_PY_TERMIOS = 0 +MICROPY_PY_USSL = 0 +MICROPY_USE_READLINE = 0 diff --git a/ports/unix/mpconfigport_nanbox.h b/ports/unix/variants/nanbox/mpconfigvariant.h similarity index 90% rename from ports/unix/mpconfigport_nanbox.h rename to ports/unix/variants/nanbox/mpconfigvariant.h index 7da2cf7b80cb0..f827158fb7127 100644 --- a/ports/unix/mpconfigport_nanbox.h +++ b/ports/unix/variants/nanbox/mpconfigvariant.h @@ -24,6 +24,10 @@ * THE SOFTWARE. */ +// This config is mostly used to ensure that the nan-boxing object model +// continues to build (i.e. catches usage of mp_obj_t that don't work with +// this representation). + // select nan-boxing object model #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) @@ -39,5 +43,3 @@ typedef int64_t mp_int_t; typedef uint64_t mp_uint_t; #define UINT_FMT "%llu" #define INT_FMT "%lld" - -#include diff --git a/ports/unix/variants/nanbox/mpconfigvariant.mk b/ports/unix/variants/nanbox/mpconfigvariant.mk new file mode 100644 index 0000000000000..b7b485b512fa5 --- /dev/null +++ b/ports/unix/variants/nanbox/mpconfigvariant.mk @@ -0,0 +1,4 @@ +# build interpreter with nan-boxing as object model (object repr D) +PROG = micropython_nanbox + +MICROPY_FORCE_32BIT = 1 diff --git a/ports/unix/variants/standard/mpconfigvariant.h b/ports/unix/variants/standard/mpconfigvariant.h new file mode 100644 index 0000000000000..79b8fe2a3be2b --- /dev/null +++ b/ports/unix/variants/standard/mpconfigvariant.h @@ -0,0 +1,26 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + diff --git a/ports/unix/variants/standard/mpconfigvariant.mk b/ports/unix/variants/standard/mpconfigvariant.mk new file mode 100644 index 0000000000000..28fad7be77752 --- /dev/null +++ b/ports/unix/variants/standard/mpconfigvariant.mk @@ -0,0 +1,16 @@ +# This is the default variant when you `make` the Unix port. + +PROG ?= micropython + +# install micropython in /usr/local/bin +TARGET = micropython +PREFIX = $(DESTDIR)/usr/local +BINDIR = $(PREFIX)/bin + +install: micropython + install -d $(BINDIR) + install $(TARGET) $(BINDIR)/$(TARGET) + +# uninstall micropython +uninstall: + -rm $(BINDIR)/$(TARGET) From 2357338e9341d6b45c1379ff9b6cbc04bf7a9241 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 28 Oct 2019 13:33:06 +1100 Subject: [PATCH 0864/1299] unix: Add placeholder DEV variant with settrace enabled. This will eventually become the "full featured" unix binary with more features enabled, specifically useful for development and testing. --- ports/unix/.gitignore | 1 + ports/unix/variants/dev/mpconfigvariant.h | 27 ++++++++++++++++++++++ ports/unix/variants/dev/mpconfigvariant.mk | 1 + 3 files changed, 29 insertions(+) create mode 100644 ports/unix/variants/dev/mpconfigvariant.h create mode 100644 ports/unix/variants/dev/mpconfigvariant.mk diff --git a/ports/unix/.gitignore b/ports/unix/.gitignore index 7179e7bde4751..977690827a249 100644 --- a/ports/unix/.gitignore +++ b/ports/unix/.gitignore @@ -1,4 +1,5 @@ micropython +micropython_dev micropython_fast micropython_minimal micropython_coverage diff --git a/ports/unix/variants/dev/mpconfigvariant.h b/ports/unix/variants/dev/mpconfigvariant.h new file mode 100644 index 0000000000000..84a3edd4547d7 --- /dev/null +++ b/ports/unix/variants/dev/mpconfigvariant.h @@ -0,0 +1,27 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define MICROPY_PY_SYS_SETTRACE (1) diff --git a/ports/unix/variants/dev/mpconfigvariant.mk b/ports/unix/variants/dev/mpconfigvariant.mk new file mode 100644 index 0000000000000..3b0f2d8967cbf --- /dev/null +++ b/ports/unix/variants/dev/mpconfigvariant.mk @@ -0,0 +1 @@ +PROG ?= micropython_dev From 7319d546b70c1ba5a34288728506c05fe4cc712d Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 23 Oct 2019 13:50:09 +1100 Subject: [PATCH 0865/1299] travis: Update travis to specify which unix variant to build. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 376e7b88e34a1..55c07bec24f03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,7 +73,7 @@ jobs: - make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix deplibs - - make ${MAKEOPTS} -C ports/unix coverage + - make ${MAKEOPTS} -C ports/unix VARIANT=coverage # run the main test suite - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread) @@ -157,7 +157,7 @@ jobs: - make ${MAKEOPTS} -C mpy-cross PYTHON=python2 - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix PYTHON=python2 deplibs - - make ${MAKEOPTS} -C ports/unix PYTHON=python2 nanbox + - make ${MAKEOPTS} -C ports/unix PYTHON=python2 VARIANT=nanbox - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_nanbox ./run-tests) # unix stackless From 977b532c8fcd1a9e12844dd4f9cc2d70341013d7 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 30 Oct 2019 17:00:09 +1100 Subject: [PATCH 0866/1299] unix: Rename unix binaries to micropython-variant (not _variant). For consistency with mpy-cross, and other unix tools in general. --- .travis.yml | 32 +++++++++---------- ports/unix/.gitignore | 7 +--- .../unix/variants/coverage/mpconfigvariant.mk | 2 +- ports/unix/variants/dev/mpconfigvariant.mk | 2 +- ports/unix/variants/fast/mpconfigvariant.mk | 2 +- .../unix/variants/freedos/mpconfigvariant.mk | 2 +- .../unix/variants/minimal/mpconfigvariant.mk | 2 +- ports/unix/variants/nanbox/mpconfigvariant.mk | 2 +- tests/run-natmodtests.py | 2 +- 9 files changed, 24 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index 55c07bec24f03..9e88ecd8fc16e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,13 +75,13 @@ jobs: - make ${MAKEOPTS} -C ports/unix deplibs - make ${MAKEOPTS} -C ports/unix VARIANT=coverage # run the main test suite - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --emit native) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy -d basics float micropython) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --emit native -d basics float micropython) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests -d thread) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests --emit native) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests --via-mpy -d basics float micropython) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests --via-mpy --emit native -d basics float micropython) # test when input script comes from stdin - - cat tests/basics/0prelim.py | ports/unix/micropython_coverage | grep -q 'abc' + - cat tests/basics/0prelim.py | ports/unix/micropython-coverage | grep -q 'abc' # test building native mpy modules - make -C examples/natmod/features1 ARCH=x64 - make -C examples/natmod/features2 ARCH=x64 @@ -92,7 +92,7 @@ jobs: - make -C examples/natmod/ure ARCH=x64 - make -C examples/natmod/uzlib ARCH=x64 # test importing .mpy generated by mpy_ld.py - - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython_coverage -m features2 + - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython-coverage -m features2 - (cd tests && ./run-natmodtests.py extmod/{btree*,framebuf*,uheapq*,ure*,uzlib*}.py) # run coveralls coverage analysis (try to, even if some builds/tests failed) - (cd ports/unix && coveralls --root ../.. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) @@ -115,13 +115,13 @@ jobs: - make ${MAKEOPTS} -C ports/unix MICROPY_FORCE_32BIT=1 deplibs - make ${MAKEOPTS} -C ports/unix MICROPY_FORCE_32BIT=1 coverage # run the main test suite - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -d thread) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --emit native) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --mpy-cross-flags='-mcache-lookup-bc -march=x86' -d basics float micropython) - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests --via-mpy --emit native --mpy-cross-flags='-mcache-lookup-bc -march=x86' -d basics float micropython) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests -d thread) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests --emit native) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests --via-mpy --mpy-cross-flags='-mcache-lookup-bc -march=x86' -d basics float micropython) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-coverage ./run-tests --via-mpy --emit native --mpy-cross-flags='-mcache-lookup-bc -march=x86' -d basics float micropython) # test when input script comes from stdin - - cat tests/basics/0prelim.py | ports/unix/micropython_coverage | grep -q 'abc' + - cat tests/basics/0prelim.py | ports/unix/micropython-coverage | grep -q 'abc' # test building native mpy modules - make -C examples/natmod/features1 ARCH=x86 - make -C examples/natmod/features2 ARCH=x86 @@ -132,7 +132,7 @@ jobs: - make -C examples/natmod/ure ARCH=x86 - make -C examples/natmod/uzlib ARCH=x86 # test importing .mpy generated by mpy_ld.py - - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython_coverage -m features2 + - MICROPYPATH=examples/natmod/features2 ./ports/unix/micropython-coverage -m features2 - (cd tests && ./run-natmodtests.py --arch x86 extmod/{btree*,framebuf*,uheapq*,ure*,uzlib*}.py) after_failure: - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) @@ -158,7 +158,7 @@ jobs: - make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix PYTHON=python2 deplibs - make ${MAKEOPTS} -C ports/unix PYTHON=python2 VARIANT=nanbox - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_nanbox ./run-tests) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-nanbox ./run-tests) # unix stackless - stage: test @@ -187,7 +187,7 @@ jobs: env: NAME="minimal unix port build and tests" script: - make ${MAKEOPTS} -C ports/unix minimal - - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython_minimal ./run-tests -e exception_chain -e self_type_check -e subclass_native_init -d basics) + - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/micropython-minimal ./run-tests -e exception_chain -e self_type_check -e subclass_native_init -d basics) # windows port via mingw - stage: test diff --git a/ports/unix/.gitignore b/ports/unix/.gitignore index 977690827a249..6745218688c20 100644 --- a/ports/unix/.gitignore +++ b/ports/unix/.gitignore @@ -1,9 +1,4 @@ micropython -micropython_dev -micropython_fast -micropython_minimal -micropython_coverage -micropython_nanbox -micropython_freedos* +micropython-* *.py *.gcov diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index e55b22eb926b2..077e7e11ac022 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -1,4 +1,4 @@ -PROG ?= micropython_coverage +PROG ?= micropython-coverage COPT = -O0 diff --git a/ports/unix/variants/dev/mpconfigvariant.mk b/ports/unix/variants/dev/mpconfigvariant.mk index 3b0f2d8967cbf..751a748f6dca1 100644 --- a/ports/unix/variants/dev/mpconfigvariant.mk +++ b/ports/unix/variants/dev/mpconfigvariant.mk @@ -1 +1 @@ -PROG ?= micropython_dev +PROG ?= micropython-dev diff --git a/ports/unix/variants/fast/mpconfigvariant.mk b/ports/unix/variants/fast/mpconfigvariant.mk index 60c1d525d35dd..e6022291d9b48 100644 --- a/ports/unix/variants/fast/mpconfigvariant.mk +++ b/ports/unix/variants/fast/mpconfigvariant.mk @@ -2,6 +2,6 @@ COPT = "-O2 -DNDEBUG -fno-crossjumping" -PROG = micropython_fast +PROG = micropython-fast FROZEN_MANIFEST = diff --git a/ports/unix/variants/freedos/mpconfigvariant.mk b/ports/unix/variants/freedos/mpconfigvariant.mk index f1d0ac21b0a5f..f7e5ed5162c83 100644 --- a/ports/unix/variants/freedos/mpconfigvariant.mk +++ b/ports/unix/variants/freedos/mpconfigvariant.mk @@ -10,7 +10,7 @@ CFLAGS_EXTRA = \ -DMICROPY_EMIT_X86=0 \ -DMICROPY_NO_ALLOCA=1 \ -PROG = micropython_freedos +PROG = micropython-freedos MICROPY_PY_SOCKET = 0 MICROPY_PY_FFI = 0 diff --git a/ports/unix/variants/minimal/mpconfigvariant.mk b/ports/unix/variants/minimal/mpconfigvariant.mk index 19f8ad64a341a..58ee64f83d12d 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.mk +++ b/ports/unix/variants/minimal/mpconfigvariant.mk @@ -1,7 +1,7 @@ # build a minimal interpreter COPT = -Os -DNDEBUG -PROG = micropython_minimal +PROG = micropython-minimal FROZEN_MANIFEST = diff --git a/ports/unix/variants/nanbox/mpconfigvariant.mk b/ports/unix/variants/nanbox/mpconfigvariant.mk index b7b485b512fa5..9752b922c1e31 100644 --- a/ports/unix/variants/nanbox/mpconfigvariant.mk +++ b/ports/unix/variants/nanbox/mpconfigvariant.mk @@ -1,4 +1,4 @@ # build interpreter with nan-boxing as object model (object repr D) -PROG = micropython_nanbox +PROG = micropython-nanbox MICROPY_FORCE_32BIT = 1 diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py index 3f49a1d68ae85..46f21f81d7822 100755 --- a/tests/run-natmodtests.py +++ b/tests/run-natmodtests.py @@ -14,7 +14,7 @@ # Paths for host executables CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') -MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython_coverage') +MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../ports/unix/micropython-coverage') NATMOD_EXAMPLE_DIR = '../examples/natmod/' From bc5c993adfa1cfb888014213fb70ef0e6916f36a Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Mon, 6 Jan 2020 09:48:16 -0800 Subject: [PATCH 0867/1299] docs/README: Add short paragraph about using readthedocs. This adds a short paragraph on how to hook readthedocs.org up. The main goal is to make people aware of the option, to help with contributing to the documentation. --- docs/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/README.md b/docs/README.md index d524f4b67e4c8..1591911c34560 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,6 +25,21 @@ In `micropython/docs`, build the docs: You'll find the index page at `micropython/docs/build/html/index.html`. +Having readthedocs.org build the documentation +---------------------------------------------- + +If you would like to have docs for forks/branches hosted on GitHub, GitLab or +BitBucket an alternative to building the docs locally is to sign up for a free +https://readthedocs.org account. The rough steps to follow are: +1. sign-up for an account, unless you already have one +2. in your account settings: add GitHub as a connected service (assuming +you have forked this repo on github) +3. in your account projects: import your forked/cloned micropython repository +into readthedocs +4. in the project's versions: add the branches you are developing on or +for which you'd like readthedocs to auto-generate docs whenever you +push a change + PDF manual generation --------------------- From df5c3bd97654c3719a62bb66627b4b538aa04b0f Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sat, 14 Dec 2019 14:38:15 +0200 Subject: [PATCH 0868/1299] py/unicode: Add unichar_isalnum(). --- py/misc.h | 1 + py/unicode.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/py/misc.h b/py/misc.h index 0aa4a5d2c6c91..12bf7b38ebfb1 100644 --- a/py/misc.h +++ b/py/misc.h @@ -140,6 +140,7 @@ bool unichar_isprint(unichar c); bool unichar_isdigit(unichar c); bool unichar_isxdigit(unichar c); bool unichar_isident(unichar c); +bool unichar_isalnum(unichar c); bool unichar_isupper(unichar c); bool unichar_islower(unichar c); unichar unichar_tolower(unichar c); diff --git a/py/unicode.c b/py/unicode.c index d69b6f56f0fde..369240e23ca31 100644 --- a/py/unicode.c +++ b/py/unicode.c @@ -140,6 +140,10 @@ bool unichar_isident(unichar c) { return c < 128 && ((attr[c] & (FL_ALPHA | FL_DIGIT)) != 0 || c == '_'); } +bool unichar_isalnum(unichar c) { + return c < 128 && ((attr[c] & (FL_ALPHA | FL_DIGIT)) != 0); +} + bool unichar_isupper(unichar c) { return c < 128 && (attr[c] & FL_UPPER) != 0; } From dce590c29dbefea253f4034c4bde3508f205364e Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 17 Dec 2019 22:40:40 +0200 Subject: [PATCH 0869/1299] lib/mp-readline: Add an assert() to catch buffer overflows. During readline development, this function may receive bad `pos` values. It's easier to understand the assert() failing error than to have a "stack smashing detected" message. --- lib/mp-readline/readline.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c index 9d254d8cfebe7..1500873f69ed1 100644 --- a/lib/mp-readline/readline.c +++ b/lib/mp-readline/readline.c @@ -74,6 +74,7 @@ STATIC void mp_hal_move_cursor_back(uint pos) { // snprintf needs space for the terminating null character int n = snprintf(&vt100_command[0], sizeof(vt100_command), "\x1b[%u", pos); if (n > 0) { + assert((unsigned)n < sizeof(vt100_command)); vt100_command[n] = 'D'; // replace null char mp_hal_stdout_tx_strn(vt100_command, n + 1); } From 853aaa06f24c98191a44a38eedd4ec2a0e63d3eb Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sat, 14 Dec 2019 23:42:03 +0200 Subject: [PATCH 0870/1299] lib/mp-readline: Add word-based move/delete EMACS key sequences. This commit adds backward-word, backward-kill-word, forward-word, forward-kill-word sequences for the REPL, with bindings to Alt+F, Alt+B, Alt+D and Alt+Backspace respectively. It is disabled by default and can be enabled via MICROPY_REPL_EMACS_WORDS_MOVE. Further enabling MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE adds extra bindings for these new sequences: Ctrl+Right, Ctrl+Left and Ctrl+W. The features are enabled on unix micropython-coverage and micropython-dev. --- lib/mp-readline/readline.c | 86 +++++++++++++++++++ lib/mp-readline/readline.h | 1 + .../unix/variants/coverage/mpconfigvariant.h | 2 + ports/unix/variants/dev/mpconfigvariant.h | 3 + py/mpconfig.h | 15 ++++ tests/cmdline/repl_words_move.py | 31 +++++++ tests/cmdline/repl_words_move.py.exp | 47 ++++++++++ tests/feature_check/repl_words_move_check.py | 4 + .../repl_words_move_check.py.exp | 7 ++ tests/run-tests | 7 +- 10 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 tests/cmdline/repl_words_move.py create mode 100644 tests/cmdline/repl_words_move.py.exp create mode 100644 tests/feature_check/repl_words_move_check.py create mode 100644 tests/feature_check/repl_words_move_check.py.exp diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c index 1500873f69ed1..296c8aa4ab543 100644 --- a/lib/mp-readline/readline.c +++ b/lib/mp-readline/readline.c @@ -99,6 +99,35 @@ typedef struct _readline_t { STATIC readline_t rl; +#if MICROPY_REPL_EMACS_WORDS_MOVE +STATIC size_t cursor_count_word(int forward) { + const char *line_buf = vstr_str(rl.line); + size_t pos = rl.cursor_pos; + bool in_word = false; + + for (;;) { + // if moving backwards and we've reached 0... break + if (!forward && pos == 0) { + break; + } + // or if moving forwards and we've reached to the end of line... break + else if (forward && pos == vstr_len(rl.line)) { + break; + } + + if (unichar_isalnum(line_buf[pos + (forward - 1)])) { + in_word = true; + } else if (in_word) { + break; + } + + pos += forward ? forward : -1; + } + + return forward ? pos - rl.cursor_pos : rl.cursor_pos - pos; +} +#endif + int readline_process_char(int c) { size_t last_line_len = rl.line->len; int redraw_step_back = 0; @@ -149,6 +178,10 @@ int readline_process_char(int c) { redraw_step_back = rl.cursor_pos - rl.orig_line_len; redraw_from_cursor = true; #endif + #if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE + } else if (c == CHAR_CTRL_W) { + goto backward_kill_word; + #endif } else if (c == '\r') { // newline mp_hal_stdout_tx_str("\r\n"); @@ -222,9 +255,40 @@ int readline_process_char(int c) { case 'O': rl.escape_seq = ESEQ_ESC_O; break; + #if MICROPY_REPL_EMACS_WORDS_MOVE + case 'b': +#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE +backward_word: +#endif + redraw_step_back = cursor_count_word(0); + rl.escape_seq = ESEQ_NONE; + break; + case 'f': +#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE +forward_word: +#endif + redraw_step_forward = cursor_count_word(1); + rl.escape_seq = ESEQ_NONE; + break; + case 'd': + vstr_cut_out_bytes(rl.line, rl.cursor_pos, cursor_count_word(1)); + redraw_from_cursor = true; + rl.escape_seq = ESEQ_NONE; + break; + case 127: +#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE +backward_kill_word: +#endif + redraw_step_back = cursor_count_word(0); + vstr_cut_out_bytes(rl.line, rl.cursor_pos - redraw_step_back, redraw_step_back); + redraw_from_cursor = true; + rl.escape_seq = ESEQ_NONE; + break; + #endif default: DEBUG_printf("(ESC %d)", c); rl.escape_seq = ESEQ_NONE; + break; } } else if (rl.escape_seq == ESEQ_ESC_BRACKET) { if ('0' <= c && c <= '9') { @@ -312,6 +376,24 @@ int readline_process_char(int c) { } else { DEBUG_printf("(ESC [ %c %d)", rl.escape_seq_buf[0], c); } + #if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE + } else if (c == ';' && rl.escape_seq_buf[0] == '1') { + // ';' is used to separate parameters. so first parameter was '1', + // that's used for sequences like ctrl+left, which we will try to parse. + // escape_seq state is reset back to ESEQ_ESC_BRACKET, as if we've just received + // the opening bracket, because more parameters are to come. + // we don't track the parameters themselves to keep low on logic and code size. that + // might be required in the future if more complex sequences are added. + rl.escape_seq = ESEQ_ESC_BRACKET; + // goto away from the state-machine, as rl.escape_seq will be overridden. + goto redraw; + } else if (rl.escape_seq_buf[0] == '5' && c == 'C') { + // ctrl+right + goto forward_word; + } else if (rl.escape_seq_buf[0] == '5' && c == 'D') { + // ctrl+left + goto backward_word; + #endif } else { DEBUG_printf("(ESC [ %c %d)", rl.escape_seq_buf[0], c); } @@ -330,6 +412,10 @@ int readline_process_char(int c) { rl.escape_seq = ESEQ_NONE; } +#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE +redraw: +#endif + // redraw command prompt, efficiently if (redraw_step_back > 0) { mp_hal_move_cursor_back(redraw_step_back); diff --git a/lib/mp-readline/readline.h b/lib/mp-readline/readline.h index 00aa9622a8023..a19e1209ab716 100644 --- a/lib/mp-readline/readline.h +++ b/lib/mp-readline/readline.h @@ -36,6 +36,7 @@ #define CHAR_CTRL_N (14) #define CHAR_CTRL_P (16) #define CHAR_CTRL_U (21) +#define CHAR_CTRL_W (23) void readline_init0(void); int readline(vstr_t *line, const char *prompt); diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index f383a837005e3..7192924534189 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -34,6 +34,8 @@ #define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_READER_VFS (1) +#define MICROPY_REPL_EMACS_WORDS_MOVE (1) +#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) #define MICROPY_WARNINGS_CATEGORY (1) #define MICROPY_MODULE_GETATTR (1) #define MICROPY_PY_DELATTR_SETATTR (1) diff --git a/ports/unix/variants/dev/mpconfigvariant.h b/ports/unix/variants/dev/mpconfigvariant.h index 84a3edd4547d7..2b30970106813 100644 --- a/ports/unix/variants/dev/mpconfigvariant.h +++ b/ports/unix/variants/dev/mpconfigvariant.h @@ -24,4 +24,7 @@ * THE SOFTWARE. */ +#define MICROPY_REPL_EMACS_WORDS_MOVE (1) +#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (1) + #define MICROPY_PY_SYS_SETTRACE (1) diff --git a/py/mpconfig.h b/py/mpconfig.h index d6f4d9232860d..2c4169070d19e 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -570,6 +570,21 @@ #define MICROPY_REPL_EMACS_KEYS (0) #endif +// Whether to include emacs-style word movement/kill readline behavior in REPL. +// This adds Alt+F, Alt+B, Alt+D and Alt+Backspace for forward-word, backward-word, forward-kill-word +// and backward-kill-word, respectively. +#ifndef MICROPY_REPL_EMACS_WORDS_MOVE +#define MICROPY_REPL_EMACS_WORDS_MOVE (0) +#endif + +// Whether to include extra convenience keys for word movement/kill in readline REPL. +// This adds Ctrl+Right, Ctrl+Left and Ctrl+W for forward-word, backward-word and backward-kill-word +// respectively. Ctrl+Delete is not implemented because it's a very different escape sequence. +// Depends on MICROPY_REPL_EMACS_WORDS_MOVE. +#ifndef MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE +#define MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE (0) +#endif + // Whether to implement auto-indent in REPL #ifndef MICROPY_REPL_AUTO_INDENT #define MICROPY_REPL_AUTO_INDENT (0) diff --git a/tests/cmdline/repl_words_move.py b/tests/cmdline/repl_words_move.py new file mode 100644 index 0000000000000..e1eb5295350c1 --- /dev/null +++ b/tests/cmdline/repl_words_move.py @@ -0,0 +1,31 @@ +# word movement +# backward-word, start in word +234b1 +# backward-word, don't start in word +234 b1 +# backward-word on start of line. if cursor is moved, this will result in a SyntaxError +1 2 + 3b+ +# forward-word, start in word +1+2 12+f+3 +# forward-word, don't start in word +1+ 12 3f+ +# forward-word on eol. if cursor is moved, this will result in a SyntaxError +1 + 2 3f+ + +# kill word +# backward-kill-word, start in word +100 + 45623 +# backward-kill-word, don't start in word +100 + 456231 +# forward-kill-word, start in word +100 + 256d3 +# forward-kill-word, don't start in word +1 + 256d2 + +# extra move/kill shortcuts +# ctrl-left +2341 +# ctrl-right +123 +# ctrl-w +1231 diff --git a/tests/cmdline/repl_words_move.py.exp b/tests/cmdline/repl_words_move.py.exp new file mode 100644 index 0000000000000..86f6b7788989e --- /dev/null +++ b/tests/cmdline/repl_words_move.py.exp @@ -0,0 +1,47 @@ +MicroPython \.\+ version +Use \.\+ +>>> # word movement +>>> # backward-word, start in word +>>> \.\+ +1234 +>>> # backward-word, don't start in word +>>> \.\+ +1234 +>>> # backward-word on start of line. if cursor is moved, this will result in a SyntaxError +>>> \.\+ +6 +>>> # forward-word, start in word +>>> \.\+ +18 +>>> # forward-word, don't start in word +>>> \.\+ +16 +>>> # forward-word on eol. if cursor is moved, this will result in a SyntaxError +>>> \.\+ +6 +>>> +>>> # kill word +>>> # backward-kill-word, start in word +>>> \.\+ +123 +>>> # backward-kill-word, don't start in word +>>> \.\+ +101 +>>> # forward-kill-word, start in word +>>> \.\+ +123 +>>> # forward-kill-word, don't start in word +>>> \.\+ +3 +>>> +>>> # extra move/kill shortcuts +>>> # ctrl-left +>>> \.\+ +1234 +>>> # ctrl-right +>>> \.\+ +123 +>>> # ctrl-w +>>> \.\+ +1 +>>> diff --git a/tests/feature_check/repl_words_move_check.py b/tests/feature_check/repl_words_move_check.py new file mode 100644 index 0000000000000..e74615e98cad3 --- /dev/null +++ b/tests/feature_check/repl_words_move_check.py @@ -0,0 +1,4 @@ +# just check if ctrl+w is supported, because it makes sure that +# both MICROPY_REPL_EMACS_WORDS_MOVE and MICROPY_REPL_EXTRA_WORDS_MOVE are enabled. +t = 1231 +t == 1 diff --git a/tests/feature_check/repl_words_move_check.py.exp b/tests/feature_check/repl_words_move_check.py.exp new file mode 100644 index 0000000000000..82a4e28ee4f84 --- /dev/null +++ b/tests/feature_check/repl_words_move_check.py.exp @@ -0,0 +1,7 @@ +MicroPython \.\+ version +Use \.\+ +>>> # Check for emacs keys in REPL +>>> t = \.\+ +>>> t == 2 +True +>>> diff --git a/tests/run-tests b/tests/run-tests index b02463dc379a8..b8f5b6b7a1858 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -284,9 +284,14 @@ def run_tests(pyb, tests, args, base_path="."): # Check if emacs repl is supported, and skip such tests if it's not t = run_feature_check(pyb, args, base_path, 'repl_emacs_check.py') - if not 'True' in str(t, 'ascii'): + if 'True' not in str(t, 'ascii'): skip_tests.add('cmdline/repl_emacs_keys.py') + # Check if words movement in repl is supported, and skip such tests if it's not + t = run_feature_check(pyb, args, base_path, 'repl_words_move_check.py') + if 'True' not in str(t, 'ascii'): + skip_tests.add('cmdline/repl_words_move.py') + upy_byteorder = run_feature_check(pyb, args, base_path, 'byteorder.py') upy_float_precision = run_feature_check(pyb, args, base_path, 'float.py') if upy_float_precision == b'CRASH': From 339d0816c55a0c62ec9be810dd3a58d36b952510 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 9 Jan 2020 16:35:13 -0600 Subject: [PATCH 0871/1299] py/runtime: Move MICROPY_PORT_INIT_FUNC near the end of mp_init(). This moves the MICROPY_PORT_INIT_FUNC hook to the end of mp_init(), just before MP_THREAD_GIL_ENTER(), so that everything (in particular the GIL mutex) is intialized before the hook is called. MICROPY_PORT_DEINIT_FUNC is also moved to be symmetric (but there is no functional change there). If a port needs to perform initialisation earlier than MICROPY_PORT_INIT_FUNC then it can do it before calling mp_init(). --- py/runtime.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/py/runtime.c b/py/runtime.c index 26b473bbe9121..db044cf7c4c15 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -81,11 +81,6 @@ void mp_init(void) { MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj; #endif - // call port specific initialization if any -#ifdef MICROPY_PORT_INIT_FUNC - MICROPY_PORT_INIT_FUNC; -#endif - #if MICROPY_ENABLE_COMPILER // optimization disabled by default MP_STATE_VM(mp_optimise_value) = 0; @@ -140,19 +135,24 @@ void mp_init(void) { mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif + // call port specific initialization if any + #ifdef MICROPY_PORT_INIT_FUNC + MICROPY_PORT_INIT_FUNC; + #endif + MP_THREAD_GIL_ENTER(); } void mp_deinit(void) { MP_THREAD_GIL_EXIT(); - //mp_obj_dict_free(&dict_main); - //mp_map_deinit(&MP_STATE_VM(mp_loaded_modules_map)); - // call port specific deinitialization if any -#ifdef MICROPY_PORT_DEINIT_FUNC + #ifdef MICROPY_PORT_DEINIT_FUNC MICROPY_PORT_DEINIT_FUNC; -#endif + #endif + + //mp_obj_dict_free(&dict_main); + //mp_map_deinit(&MP_STATE_VM(mp_loaded_modules_map)); } mp_obj_t mp_load_name(qstr qst) { From 1caede927ab946e989946d78878934a15ed3d487 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Thu, 9 Jan 2020 17:22:03 -0800 Subject: [PATCH 0872/1299] docs/library/machine: Document machine.soft_reset() function. --- docs/library/machine.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 8cc5efe593d4b..747270d936e37 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -27,6 +27,12 @@ Reset related functions Resets the device in a manner similar to pushing the external RESET button. +.. function:: soft_reset() + + Performs a soft reset of the interpreter, deleting all Python objects and + resetting the Python heap. It tries to retain the method by which the user + is connected to the MicroPython REPL (eg serial, USB, Wifi). + .. function:: reset_cause() Get the reset cause. See :ref:`constants ` for the possible return values. From 6632dd3981cbdca8e70c0bf19e36338101e9ce0e Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Thu, 9 Jan 2020 17:43:28 -0800 Subject: [PATCH 0873/1299] esp32/modmachine: Add implementation of machine.soft_reset(). --- ports/esp32/modmachine.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index e722ed2c5b2fa..6e0d0593affca 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -46,6 +46,7 @@ #include "py/obj.h" #include "py/runtime.h" +#include "lib/utils/pyexec.h" #include "extmod/machine_mem.h" #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" @@ -193,6 +194,12 @@ STATIC mp_obj_t machine_reset(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); +STATIC mp_obj_t machine_soft_reset(void) { + pyexec_system_exit = PYEXEC_FORCED_EXIT; + nlr_raise(mp_obj_new_exception(&mp_type_SystemExit)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); + STATIC mp_obj_t machine_unique_id(void) { uint8_t chipid[6]; esp_efuse_mac_get_default(chipid); @@ -228,6 +235,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) }, { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, From 7ef2f65114f092be6303c145a2560fdf522dcde0 Mon Sep 17 00:00:00 2001 From: Jason Neal Date: Sat, 11 Jan 2020 19:44:17 +1300 Subject: [PATCH 0874/1299] docs/library: Add / to indicate positional-only args in library docs. Removes the confusion of positional-only arguments which have defaults that look like keyword arguments. --- docs/library/btree.rst | 2 +- docs/library/esp.rst | 2 +- docs/library/framebuf.rst | 2 +- docs/library/machine.rst | 2 +- docs/library/sys.rst | 4 ++-- docs/library/ubluetooth.rst | 6 +++--- docs/library/uctypes.rst | 4 ++-- docs/library/uos.rst | 2 +- docs/library/ure.rst | 6 +++--- docs/library/uselect.rst | 4 ++-- docs/library/usocket.rst | 6 +++--- docs/library/ustruct.rst | 2 +- docs/library/uzlib.rst | 4 ++-- 13 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/library/btree.rst b/docs/library/btree.rst index 3578acd8fd42c..a1f7a5420f15e 100644 --- a/docs/library/btree.rst +++ b/docs/library/btree.rst @@ -116,7 +116,7 @@ Methods Flush any data in cache to the underlying stream. .. method:: btree.__getitem__(key) - btree.get(key, default=None) + btree.get(key, default=None, /) btree.__setitem__(key, val) btree.__detitem__(key) btree.__contains__(key) diff --git a/docs/library/esp.rst b/docs/library/esp.rst index 867182be9945c..cb2bc7af8d538 100644 --- a/docs/library/esp.rst +++ b/docs/library/esp.rst @@ -31,7 +31,7 @@ Functions The system enters the set sleep mode automatically when possible. -.. function:: deepsleep(time=0) +.. function:: deepsleep(time=0, /) **Note**: ESP8266 only - use `machine.deepsleep()` on ESP32 diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst index 1ff56e4dae927..43ff0b6e1b066 100644 --- a/docs/library/framebuf.rst +++ b/docs/library/framebuf.rst @@ -28,7 +28,7 @@ For example:: Constructors ------------ -.. class:: FrameBuffer(buffer, width, height, format, stride=width) +.. class:: FrameBuffer(buffer, width, height, format, stride=width, /) Construct a FrameBuffer object. The parameters are: diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 747270d936e37..b580353d6b564 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -111,7 +111,7 @@ Miscellaneous functions varies by hardware (so use substring of a full value if you expect a short ID). In some MicroPython ports, ID corresponds to the network MAC address. -.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000) +.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000, /) Time a pulse on the given *pin*, and return the duration of the pulse in microseconds. The *pulse_level* argument should be 0 to time a low pulse diff --git a/docs/library/sys.rst b/docs/library/sys.rst index d3cc308d89fb8..24f9e353bb006 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -9,7 +9,7 @@ Functions --------- -.. function:: exit(retval=0) +.. function:: exit(retval=0, /) Terminate current program with a given exit code. Underlyingly, this function raise as `SystemExit` exception. If an argument is given, its @@ -28,7 +28,7 @@ Functions This function is a MicroPython extension intended to provide similar functionality to the :mod:`atexit` module in CPython. -.. function:: print_exception(exc, file=sys.stdout) +.. function:: print_exception(exc, file=sys.stdout, /) Print exception with a traceback to a file-like object *file* (or `sys.stdout` by default). diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index 1a62d1e4bac48..e3f4e1382847e 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -268,7 +268,7 @@ writes from a central to a given characteristic, use of the notification, avoiding the need for a separate read request. Note that this will not update the local value stored. -.. method:: BLE.gatts_set_buffer(value_handle, len, append=False) +.. method:: BLE.gatts_set_buffer(value_handle, len, append=False, /) Sets the internal buffer size for a value in bytes. This will limit the largest possible write that can be received. The default is 20. @@ -283,7 +283,7 @@ writes from a central to a given characteristic, use Central Role (GATT Client) -------------------------- -.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000) +.. method:: BLE.gap_connect(addr_type, addr, scan_duration_ms=2000, /) Connect to a peripheral. @@ -326,7 +326,7 @@ Central Role (GATT Client) On success, the ``_IRQ_GATTC_READ_RESULT`` event will be raised. -.. method:: BLE.gattc_write(conn_handle, value_handle, data, mode=0) +.. method:: BLE.gattc_write(conn_handle, value_handle, data, mode=0, /) Issue a remote write to a connected peripheral for the specified characteristic or descriptor handle. diff --git a/docs/library/uctypes.rst b/docs/library/uctypes.rst index dce8caecb6e09..0fdc40e4840b4 100644 --- a/docs/library/uctypes.rst +++ b/docs/library/uctypes.rst @@ -180,7 +180,7 @@ Following are encoding examples for various field types: Module contents --------------- -.. class:: struct(addr, descriptor, layout_type=NATIVE) +.. class:: struct(addr, descriptor, layout_type=NATIVE, /) Instantiate a "foreign data structure" object based on structure address in memory, descriptor (encoded as a dictionary), and layout type (see below). @@ -200,7 +200,7 @@ Module contents Layout type for a native structure - with data endianness and alignment conforming to the ABI of the system on which MicroPython runs. -.. function:: sizeof(struct, layout_type=NATIVE) +.. function:: sizeof(struct, layout_type=NATIVE, /) Return size of data structure in bytes. The *struct* argument can be either a structure class or a specific instantiated structure object diff --git a/docs/library/uos.rst b/docs/library/uos.rst index bb7e491cce908..cbc1f3e915ee3 100644 --- a/docs/library/uos.rst +++ b/docs/library/uos.rst @@ -112,7 +112,7 @@ Filesystem access Terminal redirection and duplication ------------------------------------ -.. function:: dupterm(stream_object, index=0) +.. function:: dupterm(stream_object, index=0, /) Duplicate or switch the MicroPython terminal (the REPL) on the given `stream`-like object. The *stream_object* argument must be a native stream object, or derive diff --git a/docs/library/ure.rst b/docs/library/ure.rst index ac5f02f9e81a0..ca5f35b70302c 100644 --- a/docs/library/ure.rst +++ b/docs/library/ure.rst @@ -124,7 +124,7 @@ Functions string for first position which matches regex (which still may be 0 if regex is anchored). -.. function:: sub(regex_str, replace, string, count=0, flags=0) +.. function:: sub(regex_str, replace, string, count=0, flags=0, /) Compile *regex_str* and search for it in *string*, replacing all matches with *replace*, and returning the new string. @@ -156,14 +156,14 @@ Compiled regular expression. Instances of this class are created using .. method:: regex.match(string) regex.search(string) - regex.sub(replace, string, count=0, flags=0) + regex.sub(replace, string, count=0, flags=0, /) Similar to the module-level functions :meth:`match`, :meth:`search` and :meth:`sub`. Using methods is (much) more efficient if the same regex is applied to multiple strings. -.. method:: regex.split(string, max_split=-1) +.. method:: regex.split(string, max_split=-1, /) Split a *string* using regex. If *max_split* is given, it specifies maximum number of splits to perform. Returns list of strings (there diff --git a/docs/library/uselect.rst b/docs/library/uselect.rst index e1becc60ea410..0c3bdfdfd9360 100644 --- a/docs/library/uselect.rst +++ b/docs/library/uselect.rst @@ -58,7 +58,7 @@ Methods Modify the *eventmask* for *obj*. If *obj* is not registered, `OSError` is raised with error of ENOENT. -.. method:: poll.poll(timeout=-1) +.. method:: poll.poll(timeout=-1, /) Wait for at least one of the registered objects to become ready or have an exceptional condition, with optional timeout in milliseconds (if *timeout* @@ -81,7 +81,7 @@ Methods Tuples returned may contain more than 2 elements as described above. -.. method:: poll.ipoll(timeout=-1, flags=0) +.. method:: poll.ipoll(timeout=-1, flags=0, /) Like :meth:`poll.poll`, but instead returns an iterator which yields a `callee-owned tuple`. This function provides an efficient, allocation-free diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index 461e37b353920..e3b9d279a051e 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -66,7 +66,7 @@ Tuple address format for ``socket`` module: Functions --------- -.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP) +.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, /) Create a new socket using the given address family, socket type and protocol number. Note that specifying *proto* in most cases is not @@ -79,7 +79,7 @@ Functions # Create DGRAM UDP socket socket(AF_INET, SOCK_DGRAM) -.. function:: getaddrinfo(host, port, af=0, type=0, proto=0, flags=0) +.. function:: getaddrinfo(host, port, af=0, type=0, proto=0, flags=0, /) Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. Arguments @@ -293,7 +293,7 @@ Methods * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)`` -.. method:: socket.makefile(mode='rb', buffering=0) +.. method:: socket.makefile(mode='rb', buffering=0, /) Return a file object associated with the socket. The exact returned type depends on the arguments given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb'). diff --git a/docs/library/ustruct.rst b/docs/library/ustruct.rst index 81915d0a8d01c..357d622b2b88a 100644 --- a/docs/library/ustruct.rst +++ b/docs/library/ustruct.rst @@ -35,7 +35,7 @@ Functions Unpack from the *data* according to the format string *fmt*. The return value is a tuple of the unpacked values. -.. function:: unpack_from(fmt, data, offset=0) +.. function:: unpack_from(fmt, data, offset=0, /) Unpack from the *data* starting at *offset* according to the format string *fmt*. *offset* may be negative to count from the end of *buffer*. The return diff --git a/docs/library/uzlib.rst b/docs/library/uzlib.rst index 0b399f228ac4f..d40c46145ace9 100644 --- a/docs/library/uzlib.rst +++ b/docs/library/uzlib.rst @@ -14,7 +14,7 @@ is not yet implemented. Functions --------- -.. function:: decompress(data, wbits=0, bufsize=0) +.. function:: decompress(data, wbits=0, bufsize=0, /) Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window size used during compression (8-15, the dictionary size is power of 2 of @@ -23,7 +23,7 @@ Functions to be raw DEFLATE stream. *bufsize* parameter is for compatibility with CPython and is ignored. -.. class:: DecompIO(stream, wbits=0) +.. class:: DecompIO(stream, wbits=0, /) Create a `stream` wrapper which allows transparent decompression of compressed data in another *stream*. This allows to process compressed From ecdb30ea64af18bad44439b6718ddd5b26e7b3f9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 16 Dec 2019 15:42:59 +1100 Subject: [PATCH 0875/1299] py/nativeglue: Use mp_const_X instead of &mp_const_X_obj. --- py/nativeglue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/py/nativeglue.c b/py/nativeglue.c index 1a7f92f94517f..9be7449d201a6 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -255,9 +255,9 @@ STATIC double mp_obj_get_float_to_d(mp_obj_t o) { // these must correspond to the respective enum in runtime0.h const mp_fun_table_t mp_fun_table = { - &mp_const_none_obj, - &mp_const_false_obj, - &mp_const_true_obj, + mp_const_none, + mp_const_false, + mp_const_true, mp_native_from_obj, mp_native_to_obj, mp_native_swap_globals, From 6f0c83f6e186eb163c4209f211ab1c959d255e81 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 8 Jan 2020 23:58:40 +1100 Subject: [PATCH 0876/1299] py/obj.h: Redefine qstr object encoding to add immediate obj encoding. This commit adjusts the definition of qstr encoding in all object representations by taking a single bit from the qstr space and using it to distinguish between qstrs and a new kind of literal object: immediate objects. In other words, the qstr space is divided in two pieces, one half for qstrs and the other half for immediate objects. There is still enough room for qstr values (29 bits in representation A on a 32-bit architecture, and 19 bits in representation C) and the new immediate objects can be used for things like None, False and True. --- py/mpconfig.h | 14 +++++++++----- py/obj.h | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index 2c4169070d19e..d4a9f3c50c583 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -70,25 +70,28 @@ // A MicroPython object is a machine word having the following form: // - xxxx...xxx1 : a small int, bits 1 and above are the value -// - xxxx...xx10 : a qstr, bits 2 and above are the value +// - xxxx...x010 : a qstr, bits 3 and above are the value +// - xxxx...x110 : an immediate object, bits 3 and above are the value // - xxxx...xx00 : a pointer to an mp_obj_base_t (unless a fake object) #define MICROPY_OBJ_REPR_A (0) // A MicroPython object is a machine word having the following form: // - xxxx...xx01 : a small int, bits 2 and above are the value -// - xxxx...xx11 : a qstr, bits 2 and above are the value +// - xxxx...x011 : a qstr, bits 3 and above are the value +// - xxxx...x111 : an immediate object, bits 3 and above are the value // - xxxx...xxx0 : a pointer to an mp_obj_base_t (unless a fake object) #define MICROPY_OBJ_REPR_B (1) // A MicroPython object is a machine word having the following form (called R): // - iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int with 31-bit signed value -// - 01111111 1qqqqqqq qqqqqqqq qqqqq110 str with 20-bit qstr value +// - 01111111 1qqqqqqq qqqqqqqq qqqq0110 str with 19-bit qstr value +// - 01111111 10000000 00000000 ssss1110 immediate object with 4-bit value // - s1111111 10000000 00000000 00000010 +/- inf // - s1111111 1xxxxxxx xxxxxxxx xxxxx010 nan, x != 0 // - seeeeeee efffffff ffffffff ffffff10 30-bit fp, e != 0xff // - pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment) -// Str and float stored as O = R + 0x80800000, retrieved as R = O - 0x80800000. -// This makes strs easier to encode/decode as they have zeros in the top 9 bits. +// Str, immediate and float stored as O = R + 0x80800000, retrieved as R = O - 0x80800000. +// This makes strs/immediates easier to encode/decode as they have zeros in the top 9 bits. // This scheme only works with 32-bit word size and float enabled. #define MICROPY_OBJ_REPR_C (2) @@ -98,6 +101,7 @@ // - 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 normalised nan // - 01111111 11111101 iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int // - 01111111 11111110 00000000 00000000 qqqqqqqq qqqqqqqq qqqqqqqq qqqqqqq1 str +// - 01111111 11111111 ss000000 00000000 00000000 00000000 00000000 00000000 immediate object // - 01111111 11111100 00000000 00000000 pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment) // Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000. // This makes pointers have all zeros in the top 32 bits. diff --git a/py/obj.h b/py/obj.h index d98a0470dac62..f0bb44a403999 100644 --- a/py/obj.h +++ b/py/obj.h @@ -87,9 +87,14 @@ static inline bool mp_obj_is_small_int(mp_const_obj_t o) #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1)) static inline bool mp_obj_is_qstr(mp_const_obj_t o) - { return ((((mp_int_t)(o)) & 3) == 2); } -#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 2) -#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 2)) + { return ((((mp_int_t)(o)) & 7) == 2); } +#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 3) +#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 2)) + +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) + { return ((((mp_int_t)(o)) & 7) == 6); } +#define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) (((mp_uint_t)(o)) >> 3) +#define MP_OBJ_NEW_IMMEDIATE_OBJ(val) ((mp_obj_t)(((val) << 3) | 6)) #if MICROPY_PY_BUILTINS_FLOAT #define mp_const_float_e MP_ROM_PTR(&mp_const_float_e_obj) @@ -113,9 +118,14 @@ static inline bool mp_obj_is_small_int(mp_const_obj_t o) #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 2) | 1)) static inline bool mp_obj_is_qstr(mp_const_obj_t o) - { return ((((mp_int_t)(o)) & 3) == 3); } -#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 2) -#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 2) | 3)) + { return ((((mp_int_t)(o)) & 7) == 3); } +#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 3) +#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 3)) + +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) + { return ((((mp_int_t)(o)) & 7) == 7); } +#define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) (((mp_uint_t)(o)) >> 3) +#define MP_OBJ_NEW_IMMEDIATE_OBJ(val) ((mp_obj_t)(((val) << 3) | 7)) #if MICROPY_PY_BUILTINS_FLOAT #define mp_const_float_e MP_ROM_PTR(&mp_const_float_e_obj) @@ -161,9 +171,14 @@ static inline mp_obj_t mp_obj_new_float(mp_float_t f) { #endif static inline bool mp_obj_is_qstr(mp_const_obj_t o) - { return (((mp_uint_t)(o)) & 0xff800007) == 0x00000006; } -#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 3) -#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 0x00000006)) + { return (((mp_uint_t)(o)) & 0xff80000f) == 0x00000006; } +#define MP_OBJ_QSTR_VALUE(o) (((mp_uint_t)(o)) >> 4) +#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 4) | 0x00000006)) + +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) + { return (((mp_uint_t)(o)) & 0xff80000f) == 0x0000000e; } +#define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) (((mp_uint_t)(o)) >> 4) +#define MP_OBJ_NEW_IMMEDIATE_OBJ(val) ((mp_obj_t)(((val) << 4) | 0xe)) static inline bool mp_obj_is_obj(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 0); } @@ -180,6 +195,11 @@ static inline bool mp_obj_is_qstr(mp_const_obj_t o) #define MP_OBJ_QSTR_VALUE(o) ((((uint32_t)(o)) >> 1) & 0xffffffff) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)(((uint64_t)(((uint32_t)(qst)) << 1)) | 0x0002000000000001)) +static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) + { return ((((uint64_t)(o)) & 0xffff000000000000) == 0x0003000000000000); } +#define MP_OBJ_IMMEDIATE_OBJ_VALUE(o) ((((uint32_t)(o)) >> 46) & 3) +#define MP_OBJ_NEW_IMMEDIATE_OBJ(val) (((uint64_t)(val) << 46) | 0x0003000000000000) + #if MICROPY_PY_BUILTINS_FLOAT #if MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_DOUBLE From d96cfd13e3a464862cecffb2718c6286b52c77b0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 Jan 2020 00:00:27 +1100 Subject: [PATCH 0877/1299] py/obj: Add MICROPY_OBJ_IMMEDIATE_OBJS option to reduce code size. This option (enabled by default for object representation A, B, C) makes None/False/True objects immediate objects, ie they are no longer a concrete object in ROM but are rather just values, eg None=0x6 for representation A. Doing this saves a considerable amount of code size, due to these objects being widely used: bare-arm: -392 -0.591% minimal x86: -252 -0.170% [incl +52(data)] unix x64: -624 -0.125% [incl -128(data)] unix nanbox: +0 +0.000% stm32: -1940 -0.510% PYBV10 cc3200: -1216 -0.659% esp8266: -404 -0.062% GENERIC esp32: -732 -0.064% GENERIC[incl +48(data)] nrf: -988 -0.675% pca10040 samd: -564 -0.556% ADAFRUIT_ITSYBITSY_M4_EXPRESS Thanks go to @Jongy aka Yonatan Goldschmidt for the idea. --- py/mpconfig.h | 7 +++++++ py/obj.c | 5 +++++ py/obj.h | 29 ++++++++++++++++++++++++----- py/objbool.c | 26 +++++++++++++++++++------- py/objnone.c | 4 ++++ 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/py/mpconfig.h b/py/mpconfig.h index d4a9f3c50c583..5601cc2f77b9e 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -113,6 +113,13 @@ #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) #endif +// Whether to encode None/False/True as immediate objects instead of pointers to +// real objects. Reduces code size by a decent amount without hurting +// performance, for all representations except D on some architectures. +#ifndef MICROPY_OBJ_IMMEDIATE_OBJS +#define MICROPY_OBJ_IMMEDIATE_OBJS (MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D) +#endif + /*****************************************************************************/ /* Memory allocation policy */ diff --git a/py/obj.c b/py/obj.c index f2a884754340e..6aacfb9cf2415 100644 --- a/py/obj.c +++ b/py/obj.c @@ -46,6 +46,11 @@ const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { } else if (mp_obj_is_float(o_in)) { return &mp_type_float; #endif + #if MICROPY_OBJ_IMMEDIATE_OBJS + } else if (mp_obj_is_immediate_obj(o_in)) { + static const mp_obj_type_t *const types[2] = {&mp_type_NoneType, &mp_type_bool}; + return types[MP_OBJ_IMMEDIATE_OBJ_VALUE(o_in) & 1]; + #endif } else { const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in); return o->type; diff --git a/py/obj.h b/py/obj.h index f0bb44a403999..93433f924d6ed 100644 --- a/py/obj.h +++ b/py/obj.h @@ -263,13 +263,22 @@ typedef union _mp_rom_obj_t { uint64_t u64; struct { const void *lo, *hi; } u32; // Macros to create objects that are stored in ROM. #ifndef MP_ROM_NONE +#if MICROPY_OBJ_IMMEDIATE_OBJS +#define MP_ROM_NONE mp_const_none +#else #define MP_ROM_NONE MP_ROM_PTR(&mp_const_none_obj) #endif +#endif #ifndef MP_ROM_FALSE +#if MICROPY_OBJ_IMMEDIATE_OBJS +#define MP_ROM_FALSE mp_const_false +#define MP_ROM_TRUE mp_const_true +#else #define MP_ROM_FALSE MP_ROM_PTR(&mp_const_false_obj) #define MP_ROM_TRUE MP_ROM_PTR(&mp_const_true_obj) #endif +#endif #ifndef MP_ROM_INT typedef mp_const_obj_t mp_rom_obj_t; @@ -622,17 +631,27 @@ extern const mp_obj_type_t mp_type_ValueError; extern const mp_obj_type_t mp_type_ViperTypeError; extern const mp_obj_type_t mp_type_ZeroDivisionError; -// Constant objects, globally accessible -// The macros are for convenience only +// Constant objects, globally accessible: None, False, True +// These should always be accessed via the below macros. +#if MICROPY_OBJ_IMMEDIATE_OBJS +// None is even while False/True are odd so their types can be distinguished with 1 bit. +#define mp_const_none MP_OBJ_NEW_IMMEDIATE_OBJ(0) +#define mp_const_false MP_OBJ_NEW_IMMEDIATE_OBJ(1) +#define mp_const_true MP_OBJ_NEW_IMMEDIATE_OBJ(3) +#else #define mp_const_none (MP_OBJ_FROM_PTR(&mp_const_none_obj)) #define mp_const_false (MP_OBJ_FROM_PTR(&mp_const_false_obj)) #define mp_const_true (MP_OBJ_FROM_PTR(&mp_const_true_obj)) -#define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&mp_const_empty_bytes_obj)) -#define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&mp_const_empty_tuple_obj)) -#define mp_const_notimplemented (MP_OBJ_FROM_PTR(&mp_const_notimplemented_obj)) extern const struct _mp_obj_none_t mp_const_none_obj; extern const struct _mp_obj_bool_t mp_const_false_obj; extern const struct _mp_obj_bool_t mp_const_true_obj; +#endif + +// Constant objects, globally accessible: b'', (), Ellipsis, NotImplemented, GeneratorExit() +// The below macros are for convenience only. +#define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&mp_const_empty_bytes_obj)) +#define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&mp_const_empty_tuple_obj)) +#define mp_const_notimplemented (MP_OBJ_FROM_PTR(&mp_const_notimplemented_obj)) extern const struct _mp_obj_str_t mp_const_empty_bytes_obj; extern const struct _mp_obj_tuple_t mp_const_empty_tuple_obj; extern const struct _mp_obj_singleton_t mp_const_ellipsis_obj; diff --git a/py/objbool.c b/py/objbool.c index 5755b188e98cd..4c046ac8f2f25 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -28,21 +28,31 @@ #include "py/runtime.h" +#if MICROPY_OBJ_IMMEDIATE_OBJS + +#define BOOL_VALUE(o) ((o) == mp_const_false ? 0 : 1) + +#else + +#define BOOL_VALUE(o) (((mp_obj_bool_t*)MP_OBJ_TO_PTR(o))->value) + typedef struct _mp_obj_bool_t { mp_obj_base_t base; bool value; } mp_obj_bool_t; +#endif + STATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - mp_obj_bool_t *self = MP_OBJ_TO_PTR(self_in); + bool value = BOOL_VALUE(self_in); if (MICROPY_PY_UJSON && kind == PRINT_JSON) { - if (self->value) { + if (value) { mp_print_str(print, "true"); } else { mp_print_str(print, "false"); } } else { - if (self->value) { + if (value) { mp_print_str(print, "True"); } else { mp_print_str(print, "False"); @@ -65,13 +75,13 @@ STATIC mp_obj_t bool_unary_op(mp_unary_op_t op, mp_obj_t o_in) { if (op == MP_UNARY_OP_LEN) { return MP_OBJ_NULL; } - mp_obj_bool_t *self = MP_OBJ_TO_PTR(o_in); - return mp_unary_op(op, MP_OBJ_NEW_SMALL_INT(self->value)); + bool value = BOOL_VALUE(o_in); + return mp_unary_op(op, MP_OBJ_NEW_SMALL_INT(value)); } STATIC mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { - mp_obj_bool_t *self = MP_OBJ_TO_PTR(lhs_in); - return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(self->value), rhs_in); + bool value = BOOL_VALUE(lhs_in); + return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(value), rhs_in); } const mp_obj_type_t mp_type_bool = { @@ -83,5 +93,7 @@ const mp_obj_type_t mp_type_bool = { .binary_op = bool_binary_op, }; +#if !MICROPY_OBJ_IMMEDIATE_OBJS const mp_obj_bool_t mp_const_false_obj = {{&mp_type_bool}, false}; const mp_obj_bool_t mp_const_true_obj = {{&mp_type_bool}, true}; +#endif diff --git a/py/objnone.c b/py/objnone.c index da1031835c710..271a8543f9718 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -28,9 +28,11 @@ #include "py/obj.h" +#if !MICROPY_OBJ_IMMEDIATE_OBJS typedef struct _mp_obj_none_t { mp_obj_base_t base; } mp_obj_none_t; +#endif STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)self_in; @@ -48,4 +50,6 @@ const mp_obj_type_t mp_type_NoneType = { .unary_op = mp_generic_unary_op, }; +#if !MICROPY_OBJ_IMMEDIATE_OBJS const mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}}; +#endif From 40057600b873b2a802de332d251492a762b32011 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 9 Jan 2020 11:19:26 +1100 Subject: [PATCH 0878/1299] py/obj: Optimise mp_obj_get_type for immediate objs with repr A and C. This function is called often and with immediate objects enabled it has more cases, so optimise it for speed. With this optimisation the runtime is now slightly faster with immediate objects enabled than with them disabled. --- py/obj.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/py/obj.c b/py/obj.c index 6aacfb9cf2415..55754f9be27e7 100644 --- a/py/obj.c +++ b/py/obj.c @@ -38,11 +38,47 @@ #include "py/stream.h" // for mp_obj_print const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { + #if MICROPY_OBJ_IMMEDIATE_OBJS && MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A + + if (mp_obj_is_obj(o_in)) { + const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in); + return o->type; + } else { + static const mp_obj_type_t *const types[] = { + NULL, &mp_type_int, &mp_type_str, &mp_type_int, + NULL, &mp_type_int, &mp_type_NoneType, &mp_type_int, + NULL, &mp_type_int, &mp_type_str, &mp_type_int, + NULL, &mp_type_int, &mp_type_bool, &mp_type_int, + }; + return types[(uintptr_t)o_in & 0xf]; + } + + #elif MICROPY_OBJ_IMMEDIATE_OBJS && MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C + + if (mp_obj_is_small_int(o_in)) { + return &mp_type_int; + } else if (mp_obj_is_obj(o_in)) { + const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in); + return o->type; + #if MICROPY_PY_BUILTINS_FLOAT + } else if ((((mp_uint_t)(o_in)) & 0xff800007) != 0x00000006) { + return &mp_type_float; + #endif + } else { + static const mp_obj_type_t *const types[] = { + &mp_type_str, &mp_type_NoneType, &mp_type_str, &mp_type_bool, + }; + return types[((uintptr_t)o_in >> 3) & 3]; + } + + #else + if (mp_obj_is_small_int(o_in)) { return &mp_type_int; } else if (mp_obj_is_qstr(o_in)) { return &mp_type_str; - #if MICROPY_PY_BUILTINS_FLOAT + #if MICROPY_PY_BUILTINS_FLOAT && ( \ + MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) } else if (mp_obj_is_float(o_in)) { return &mp_type_float; #endif @@ -55,6 +91,8 @@ const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) { const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in); return o->type; } + + #endif } const char *mp_obj_get_type_str(mp_const_obj_t o_in) { From 1c849d63a86782f006b73a9d570d542cfd18538e Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sun, 1 Dec 2019 01:10:12 +0200 Subject: [PATCH 0879/1299] py/mpconfig.h: Define BITS_PER_BYTE only if not already defined. It's a common macro that is possibly defined in headers of systems/SDKs MicroPython is embedded into. --- py/mpconfig.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/py/mpconfig.h b/py/mpconfig.h index 5601cc2f77b9e..8e06153a83b0c 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1468,7 +1468,9 @@ typedef double mp_float_t; #define BYTES_PER_WORD (sizeof(mp_uint_t)) #endif +#ifndef BITS_PER_BYTE #define BITS_PER_BYTE (8) +#endif #define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD) // mp_int_t value with most significant bit set #define WORD_MSBIT_HIGH (((mp_uint_t)1) << (BYTES_PER_WORD * 8 - 1)) From 176ab99180a95eeac8794828f2f751a696571bb5 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 13 Jan 2020 23:35:07 +0200 Subject: [PATCH 0880/1299] py/objint: Add mp_obj_int_get_uint_checked() helper. Can be used where mp_obj_int_get_checked() will overflow due to the sign-bit solely. This returns an mp_uint_t, so it also verifies the given integer is not negative. Currently implemented only for mpz configurations. --- py/obj.h | 2 ++ py/objint_mpz.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/py/obj.h b/py/obj.h index 93433f924d6ed..ba4f4992fffab 100644 --- a/py/obj.h +++ b/py/obj.h @@ -748,6 +748,8 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in); // Will raise exception if value doesn't fit into mp_int_t mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); +// Will raise exception if value is negative or doesn't fit into mp_uint_t +mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in); // exception #define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new) diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 121fd03424893..2c09d9bd2bff1 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -411,6 +411,22 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { } } +mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { + if (mp_obj_is_small_int(self_in)) { + if (MP_OBJ_SMALL_INT_VALUE(self_in) >= 0) { + return MP_OBJ_SMALL_INT_VALUE(self_in); + } + } else { + const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); + mp_uint_t value; + if (mpz_as_uint_checked(&self->mpz, &value)) { + return value; + } + } + + mp_raise_msg(&mp_type_OverflowError, "overflow converting long int to machine word"); +} + #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_int)); From 3448e69c2d6f6f066907005f56bbd26fffb756e9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 14 Jan 2020 23:45:56 +1100 Subject: [PATCH 0881/1299] tests/unix: Add coverage test for new mp_obj_int_get_uint_checked func. --- ports/unix/coverage.c | 23 +++++++++++++++++++++++ tests/unix/extra_coverage.py.exp | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 6623cb4642bc2..6cd84dc301192 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -334,6 +334,29 @@ STATIC mp_obj_t extra_coverage(void) { mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(1)); // call mp_call_function_2_protected with invalid args mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str("abc", 3), mp_obj_new_str("abc", 3)); + + // mp_obj_int_get_uint_checked with non-negative small-int + mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1))); + + // mp_obj_int_get_uint_checked with non-negative big-int + mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(2))); + + // mp_obj_int_get_uint_checked with negative small-int (should raise exception) + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(-1)); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + + // mp_obj_int_get_uint_checked with negative big-int (should raise exception) + if (nlr_push(&nlr) == 0) { + mp_obj_int_get_uint_checked(mp_obj_new_int_from_ll(-2)); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } } // warning diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 8922f96162b84..6aa2da31a4a8c 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -54,6 +54,10 @@ data # runtime utils TypeError: unsupported type for __abs__: 'str' TypeError: unsupported types for __divmod__: 'str', 'str' +1 +2 +OverflowError: overflow converting long int to machine word +OverflowError: overflow converting long int to machine word Warning: test # format float ? From 4ab4bf3ec6e891a49a827b659d5d4764a40ee404 Mon Sep 17 00:00:00 2001 From: Memiks Date: Wed, 8 Jan 2020 09:38:20 +0900 Subject: [PATCH 0882/1299] ports: Modify mp_hal_pin_write macro so it can be used as a function. Even though it doesn't return anything it could still be used like a function. Addresses issue #5501. --- ports/nrf/mphalport.h | 2 +- ports/stm32/mboot/mphalport.h | 2 +- ports/stm32/mphalport.h | 2 +- ports/teensy/teensy_hal.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index b374da403c8f7..23df0c0cf0e23 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -65,7 +65,7 @@ const char * nrfx_error_code_lookup(uint32_t err_code); #define mp_hal_pin_high(p) nrf_gpio_pin_set(p->pin) #define mp_hal_pin_low(p) nrf_gpio_pin_clear(p->pin) #define mp_hal_pin_read(p) (nrf_gpio_pin_dir_get(p->pin) == NRF_GPIO_PIN_DIR_OUTPUT) ? nrf_gpio_pin_out_read(p->pin) : nrf_gpio_pin_read(p->pin) -#define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) +#define mp_hal_pin_write(p, v) ((v) ? mp_hal_pin_high(p) : mp_hal_pin_low(p)) #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_open_drain(p) nrf_gpio_cfg_input(p->pin, NRF_GPIO_PIN_NOPULL) diff --git a/ports/stm32/mboot/mphalport.h b/ports/stm32/mboot/mphalport.h index 86063c4ef2438..0c8cb91a6883a 100644 --- a/ports/stm32/mboot/mphalport.h +++ b/ports/stm32/mboot/mphalport.h @@ -53,7 +53,7 @@ #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_read(p) ((((GPIO_TypeDef*)((p) & ~0xf))->IDR >> ((p) & 0xf)) & 1) -#define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) +#define mp_hal_pin_write(p, v) ((v) ? mp_hal_pin_high(p) : mp_hal_pin_low(p)) void mp_hal_pin_config(uint32_t port_pin, uint32_t mode, uint32_t pull, uint32_t alt); void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed); diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h index d73ff8bff36f7..ce3c51f8d64cb 100644 --- a/ports/stm32/mphalport.h +++ b/ports/stm32/mphalport.h @@ -68,7 +68,7 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) { #define mp_hal_pin_od_low(p) mp_hal_pin_low(p) #define mp_hal_pin_od_high(p) mp_hal_pin_high(p) #define mp_hal_pin_read(p) (((p)->gpio->IDR >> (p)->pin) & 1) -#define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) +#define mp_hal_pin_write(p, v) ((v) ? mp_hal_pin_high(p) : mp_hal_pin_low(p)) void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio); void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt); diff --git a/ports/teensy/teensy_hal.h b/ports/teensy/teensy_hal.h index aef38a2ad9ecb..f2e66821ddb54 100644 --- a/ports/teensy/teensy_hal.h +++ b/ports/teensy/teensy_hal.h @@ -125,4 +125,4 @@ struct _pin_obj_t; #define mp_hal_pin_high(p) (((p)->gpio->PSOR) = (p)->pin_mask) #define mp_hal_pin_low(p) (((p)->gpio->PCOR) = (p)->pin_mask) #define mp_hal_pin_read(p) (((p)->gpio->PDIR >> (p)->pin) & 1) -#define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) +#define mp_hal_pin_write(p, v) ((v) ? mp_hal_pin_high(p) : mp_hal_pin_low(p)) From c14ff6194c224190c7e6787a2bffbdbb495be4b4 Mon Sep 17 00:00:00 2001 From: JensDiemer Date: Thu, 9 Jan 2020 16:33:31 +0100 Subject: [PATCH 0883/1299] esp8266/modules: Fix AttributeError in _boot.py if flash not formatted. Prior to this commit, if the flash filesystem was not formatted then it would error: "AttributeError: 'FlashBdev' object has no attribute 'mount'". That is due to it not being able to detect the filesystem on the block device and just trying to mount the block device directly. This commit fixes the issue by just catching all exceptions. Also it's not needed to try the mount if `flashbdev.bdev` is None. --- ports/esp8266/modules/_boot.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/esp8266/modules/_boot.py b/ports/esp8266/modules/_boot.py index 81eb20dd631ef..4c2aa87fe54e4 100644 --- a/ports/esp8266/modules/_boot.py +++ b/ports/esp8266/modules/_boot.py @@ -3,11 +3,11 @@ import uos from flashbdev import bdev -try: - if bdev: +if bdev: + try: uos.mount(bdev, '/') -except OSError: - import inisetup - inisetup.setup() + except: + import inisetup + inisetup.setup() gc.collect() From 3032ae1155db4bd89786f715f5227967d2cb71cf Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Mon, 16 Dec 2019 12:36:38 +1100 Subject: [PATCH 0884/1299] esp32: Enable NimBLE support on all builds (IDF 3.3 and 4.0). This commit updates the IDFv3 version to v3.3.1, and enables the "ubluetooth" module by default on IDFv3 builds. --- .travis.yml | 2 +- ports/esp32/Makefile | 63 ++++++++++++++++++++++++++----- ports/esp32/boards/sdkconfig.base | 1 + ports/esp32/boards/sdkconfig.ble | 10 +++++ 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9e88ecd8fc16e..c785eb47a1f04 100644 --- a/.travis.yml +++ b/.travis.yml @@ -213,7 +213,7 @@ jobs: - make ${MAKEOPTS} -C mpy-cross # IDF v3 build - git -C esp-idf checkout $(grep "ESPIDF_SUPHASH_V3 :=" ports/esp32/Makefile | cut -d " " -f 3) - - git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 + - git -C esp-idf submodule update --init components/json/cJSON components/esp32/lib components/esptool_py/esptool components/expat/expat components/lwip/lwip components/mbedtls/mbedtls components/micro-ecc/micro-ecc components/nghttp/nghttp2 components/nimble components/bt - make ${MAKEOPTS} -C ports/esp32 submodules - make ${MAKEOPTS} -C ports/esp32 # clean diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index a9002b651217e..65907a3ee0f0a 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -51,8 +51,9 @@ OBJDUMP = $(CROSS_COMPILE)objdump SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined SDKCONFIG_H = $(BUILD)/sdkconfig.h -# the git hash of the currently supported ESP IDF version -ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df +# The git hash of the currently supported ESP IDF version. +# These correspond to v3.3.1 and v4.0-beta1. +ESPIDF_SUPHASH_V3 := 143d26aa49df524e10fb8e41a71d12e731b9b71d ESPIDF_SUPHASH_V4 := 310beae373446ceb9a4ad9b36b5428d7fdf2705f define print_supported_git_hash @@ -112,15 +113,13 @@ $(info Add the xtensa toolchain to your PATH. See README.md) $(error C compiler missing) endif -# Support BLE by default when building with IDF 4.x. +# Support BLE by default. # Can be explicitly disabled on the command line or board config. -ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) MICROPY_PY_BLUETOOTH ?= 1 ifeq ($(MICROPY_PY_BLUETOOTH),1) SDKCONFIG += boards/sdkconfig.ble MICROPY_BLUETOOTH_NIMBLE = 1 endif -endif # include sdkconfig to get needed configuration values include $(SDKCONFIG) @@ -158,6 +157,7 @@ INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/lwip/src/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps +INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps/sntp INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include INC_ESPCOMP += -I$(ESPCOMP)/mdns/include @@ -218,9 +218,28 @@ INC_ESPCOMP += -I$(ESPCOMP)/json/port/include INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes +ifeq ($(CONFIG_NIMBLE_ENABLED),y) +INC_ESPCOMP += -I$(ESPCOMP)/bt/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/porting/nimble/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/port/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/ans/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/bas/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/gap/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/gatt/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/ias/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/lls/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/services/tps/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/util/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/store/ram/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/nimble/host/store/config/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/porting/npl/freertos/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/nimble/ext/tinycrypt/include +INC_ESPCOMP += -I$(ESPCOMP)/nimble/esp-hci/include +endif endif -ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) ifeq ($(MICROPY_PY_BLUETOOTH),1) CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1 CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 @@ -229,7 +248,6 @@ ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 endif endif -endif # these flags are common to C and C++ compilation CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ @@ -421,6 +439,7 @@ ESPIDF_SOC_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/soc/src/hal/*.c) \ ) +$(BUILD)/$(ESPCOMP)/cxx/cxx_guards.o: CXXFLAGS += -Wno-error=sign-compare ESPIDF_CXX_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/cxx/*.cpp)) ESPIDF_PTHREAD_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/pthread/*.c)) @@ -458,6 +477,7 @@ ESPIDF_APP_UPDATE_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/app_update/*.c)) ESPIDF_NEWLIB_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/newlib/*.c)) +$(BUILD)/$(ESPCOMP)/nvs_flash/src/nvs_api.o: CXXFLAGS += -Wno-error=sign-compare ESPIDF_NVS_FLASH_O = $(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/nvs_flash/src/*.cpp)) ESPIDF_SMARTCONFIG_ACK_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/smartconfig_ack/*.c)) @@ -546,6 +566,29 @@ ESPIDF_ETHERNET_O = $(patsubst %.c,%.o,\ $(wildcard $(ESPCOMP)/ethernet/*.c) \ $(wildcard $(ESPCOMP)/ethernet/eth_phy/*.c) \ ) + +ifeq ($(CONFIG_NIMBLE_ENABLED),y) +ESPIDF_BT_NIMBLE_O = $(patsubst %.c,%.o,\ + $(wildcard $(ESPCOMP)/bt/*.c) \ + $(wildcard $(ESPCOMP)/nimble/esp-hci/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/ext/tinycrypt/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/ans/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/bas/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/gap/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/gatt/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/ias/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/lls/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/services/tps/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/store/config/src/ble_store_config.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/store/ram/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/host/util/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/nimble/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/porting/nimble/src/*.c) \ + $(wildcard $(ESPCOMP)/nimble/nimble/porting/npl/freertos/src/*.c) \ + ) +endif endif OBJ_ESPIDF = @@ -587,14 +630,12 @@ $(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O))) $(eval $(call gen_espidf_lib_rule,mdns,$(ESPIDF_MDNS_O))) $(eval $(call gen_espidf_lib_rule,wpa_supplicant,$(ESPIDF_WPA_SUPPLICANT_O))) $(eval $(call gen_espidf_lib_rule,sdmmc,$(ESPIDF_SDMMC_O))) +$(eval $(call gen_espidf_lib_rule,bt_nimble,$(ESPIDF_BT_NIMBLE_O))) ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) $(eval $(call gen_espidf_lib_rule,esp_common,$(ESPIDF_ESP_COMMON_O))) $(eval $(call gen_espidf_lib_rule,esp_event,$(ESPIDF_ESP_EVENT_O))) $(eval $(call gen_espidf_lib_rule,esp_wifi,$(ESPIDF_ESP_WIFI_O))) -ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) -$(eval $(call gen_espidf_lib_rule,bt_nimble,$(ESPIDF_BT_NIMBLE_O))) -endif $(eval $(call gen_espidf_lib_rule,esp_eth,$(ESPIDF_ESP_ETH_O))) $(eval $(call gen_espidf_lib_rule,xtensa,$(ESPIDF_XTENSA_O))) else @@ -714,6 +755,7 @@ APP_LD_ARGS += -L$(ESPCOMP)/bt/controller/lib -lbtdm_app APP_LD_ARGS += -L$(ESPCOMP)/esp_wifi/lib_esp32 -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lsmartconfig -lcoexist else APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a +APP_LD_ARGS += -L$(ESPCOMP)/bt/lib -lbtdm_app APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2 endif APP_LD_ARGS += $(OBJ) @@ -769,6 +811,7 @@ BOOTLOADER_LIB_BOOTLOADER_SUPPORT_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOM bootloader_support/src/bootloader_clock.o \ bootloader_support/src/bootloader_common.o \ bootloader_support/src/bootloader_flash.o \ + bootloader_support/src/bootloader_flash_config.o \ bootloader_support/src/bootloader_init.o \ bootloader_support/src/bootloader_random.o \ bootloader_support/src/bootloader_utility.o \ diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base index dcb7742d3d474..f44ec4e173e9b 100644 --- a/ports/esp32/boards/sdkconfig.base +++ b/ports/esp32/boards/sdkconfig.base @@ -2,6 +2,7 @@ # The following options override the defaults CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 # Application manager CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y diff --git a/ports/esp32/boards/sdkconfig.ble b/ports/esp32/boards/sdkconfig.ble index 15422903c1890..cdbb621a63112 100644 --- a/ports/esp32/boards/sdkconfig.ble +++ b/ports/esp32/boards/sdkconfig.ble @@ -12,3 +12,13 @@ CONFIG_BT_NIMBLE_MAX_CONNECTIONS=4 CONFIG_BT_NIMBLE_PINNED_TO_CORE_0=n CONFIG_BT_NIMBLE_PINNED_TO_CORE_1=y CONFIG_BT_NIMBLE_PINNED_TO_CORE=1 + +# v3.3-only (renamed in 4.0) +CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y +CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CONTROLLER_MODE_BTDM= +CONFIG_BLUEDROID_ENABLED=n +CONFIG_NIMBLE_ENABLED=y +CONFIG_NIMBLE_MAX_CONNECTIONS=4 +CONFIG_NIMBLE_PINNED_TO_CORE_0=n +CONFIG_NIMBLE_PINNED_TO_CORE_1=y From 5c5f93c1b896a8e73eff2edb3a3f3a2615b3f4de Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Thu, 16 Jan 2020 09:07:50 -0800 Subject: [PATCH 0885/1299] tests: Make run-tests help and README be more descriptive of behaviour. --- tests/README | 9 +++++++++ tests/run-tests | 11 +++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/README b/tests/README index 3458f36a80201..f2cd89bb932a3 100644 --- a/tests/README +++ b/tests/README @@ -13,6 +13,15 @@ condition a test. The run-tests script uses small scripts in the feature_check directory to check whether each such feature is present, and skips the relevant tests if not. +Tests are generally verified by running the test both in MicroPython and +in CPython and comparing the outputs. If the output differs the test fails +and the outputs are saved in a .out and a .exp file respectively. +For tests that cannot be run in CPython, for example because they use +the machine module, a .exp file can be provided next to the test's .py +file. A convenient way to generate that is to run the test, let it fail +(because CPython cannot run it) and then copy the .out file (but not +before checking it manually!) + When creating new tests, anything that relies on float support should go in the float/ subdirectory. Anything that relies on import x, where x is not a built-in module, should go in the import/ subdirectory. diff --git a/tests/run-tests b/tests/run-tests index b8f5b6b7a1858..f0fa83407011d 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -553,7 +553,14 @@ class append_filter(argparse.Action): def main(): cmd_parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, - description='Run and manage tests for MicroPython.', + description='''Run and manage tests for MicroPython. + +When running tests, run-tests compares the MicroPython output of the test with the output +produced by running the test through CPython unless a .exp file is found, in which +case it is used as comparison. +If a test fails, run-tests produces a pair of .out and .exp files in the current +directory with the MicroPython output and the expectations, respectively. +''', epilog='''\ Options -i and -e can be multiple and processed in the order given. Regex "search" (vs "match") operation is used. An action (include/exclude) of @@ -570,7 +577,7 @@ the last matching regex is used: cmd_parser.add_argument('-d', '--test-dirs', nargs='*', help='input test directories (if no files given)') cmd_parser.add_argument('-e', '--exclude', action=append_filter, metavar='REGEX', dest='filters', help='exclude test by regex on path/name.py') cmd_parser.add_argument('-i', '--include', action=append_filter, metavar='REGEX', dest='filters', help='include test by regex on path/name.py') - cmd_parser.add_argument('--write-exp', action='store_true', help='save .exp files to run tests w/o CPython') + cmd_parser.add_argument('--write-exp', action='store_true', help='use CPython to generate .exp files to run tests w/o CPython') cmd_parser.add_argument('--list-tests', action='store_true', help='list tests instead of running them') cmd_parser.add_argument('--emit', default='bytecode', help='MicroPython emitter to use (bytecode or native)') cmd_parser.add_argument('--heapsize', help='heapsize to use (use default if not specified)') From 59746ac14a7e639b8abd50fe626549e115c19c68 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Sun, 12 Jan 2020 09:20:36 +0000 Subject: [PATCH 0886/1299] docs/library/uos.rst: Improve block devices section, and ioctl ret vals. --- docs/library/uos.rst | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/docs/library/uos.rst b/docs/library/uos.rst index cbc1f3e915ee3..c49b13a5f5bca 100644 --- a/docs/library/uos.rst +++ b/docs/library/uos.rst @@ -218,11 +218,19 @@ represented by VFS classes. Block devices ------------- -A block device is an object which implements the block protocol, which is a set -of methods described below by the :class:`AbstractBlockDev` class. A concrete -implementation of this class will usually allow access to the memory-like -functionality a piece of hardware (like flash memory). A block device can be -used by a particular filesystem driver to store the data for its filesystem. +A block device is an object which implements the block protocol. This enables a +device to support MicroPython filesystems. The physical hardware is represented +by a user defined class. The :class:`AbstractBlockDev` class is a template for +the design of such a class: MicroPython does not actually provide that class, +but an actual block device class must implement the methods described below. + +A concrete implementation of this class will usually allow access to the +memory-like functionality of a piece of hardware (like flash memory). A block +device can be formatted to any supported filesystem and mounted using ``uos`` +methods. + +See :ref:`filesystem` for example implementations of block devices using the +two variants of the block protocol described below. .. _block-device-interface: @@ -294,5 +302,12 @@ that the block device supports the extended interface. (*arg* is unused) - 6 -- erase a block, *arg* is the block number to erase -See :ref:`filesystem` for example implementations of block devices using both -protocols. + As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs + ``ioctl(6, ...)`` must also be intercepted. The need for others is + hardware dependent. + + Unless otherwise stated ``ioctl(op, arg)`` can return ``None``. + Consequently an implementation can ignore unused values of ``op``. Where + ``op`` is intercepted, the return value for operations 4 and 5 are as + detailed above. Other operations should return 0 on success and non-zero + for failure, with the value returned being an ``OSError`` errno code. From a55c17dc69ac43cd41e7efe603e20298a5513b06 Mon Sep 17 00:00:00 2001 From: adzierzanowski Date: Thu, 16 Jan 2020 11:16:43 +0100 Subject: [PATCH 0887/1299] esp32/modnetwork: Add max_clients kw-arg to WLAN.config for AP setting. This allows the user to configure the maximum number of clients that are connected to the access point. Resolves #5125. --- docs/esp32/quickref.rst | 1 + ports/esp32/modnetwork.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index c58f4aa760856..8861ca4ac87ed 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -82,6 +82,7 @@ The :mod:`network` module:: ap = network.WLAN(network.AP_IF) # create access-point interface ap.config(essid='ESP-AP') # set the ESSID of the access point + ap.config(max_clients=10) # set how many clients can connect to the network ap.active(True) # activate the interface A useful function for connecting to your local WiFi network is:: diff --git a/ports/esp32/modnetwork.c b/ports/esp32/modnetwork.c index ba967b8cbd081..06aa1c4b16ab2 100644 --- a/ports/esp32/modnetwork.c +++ b/ports/esp32/modnetwork.c @@ -619,6 +619,11 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs ESP_EXCEPTIONS(tcpip_adapter_set_hostname(self->if_id, s)); break; } + case QS(MP_QSTR_max_clients): { + req_if = WIFI_IF_AP; + cfg.ap.max_connection = mp_obj_get_int(kwargs->table[i].value); + break; + } default: goto unknown; } @@ -693,6 +698,10 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs val = mp_obj_new_str(s, strlen(s)); break; } + case QS(MP_QSTR_max_clients): { + val = MP_OBJ_NEW_SMALL_INT(cfg.ap.max_connection); + break; + } default: goto unknown; } From 599371b133ec24c8ccfc3b75dd5a62b94b4b4055 Mon Sep 17 00:00:00 2001 From: stijn Date: Mon, 13 Jan 2020 12:11:27 +0100 Subject: [PATCH 0888/1299] windows: Support word-based move/delete key sequences for REPL. Translate common Ctrl-Left/Right/Delete/Backspace to the EMACS-style sequences (i.e. Alt key based) for forward-word, backward-word, forwad-kill and backward-kill. Requires MICROPY_REPL_EMACS_WORDS_MOVE to be defined so the readline implementation interprets these. --- ports/windows/windows_mphal.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/ports/windows/windows_mphal.c b/ports/windows/windows_mphal.c index 1e3a09291060e..1ec8e27d6aea8 100644 --- a/ports/windows/windows_mphal.c +++ b/ports/windows/windows_mphal.c @@ -141,7 +141,7 @@ typedef struct item_t { const char *seq; } item_t; -// map virtual key codes to VT100 escape sequences +// map virtual key codes to key sequences known by MicroPython's readline implementation STATIC item_t keyCodeMap[] = { {VK_UP, "[A"}, {VK_DOWN, "[B"}, @@ -153,10 +153,19 @@ STATIC item_t keyCodeMap[] = { {0, ""} //sentinel }; +// likewise, but with Ctrl key down +STATIC item_t ctrlKeyCodeMap[] = { + {VK_LEFT, "b"}, + {VK_RIGHT, "f"}, + {VK_DELETE, "d"}, + {VK_BACK, "\x7F"}, + {0, ""} //sentinel +}; + STATIC const char *cur_esc_seq = NULL; -STATIC int esc_seq_process_vk(int vk) { - for (item_t *p = keyCodeMap; p->vkey != 0; ++p) { +STATIC int esc_seq_process_vk(WORD vk, bool ctrl_key_down) { + for (item_t *p = (ctrl_key_down ? ctrlKeyCodeMap : keyCodeMap); p->vkey != 0; ++p) { if (p->vkey == vk) { cur_esc_seq = p->seq; return 27; // ESC, start of escape sequence @@ -194,14 +203,16 @@ int mp_hal_stdin_rx_chr(void) { if (rec.EventType != KEY_EVENT || !rec.Event.KeyEvent.bKeyDown) { // only want key down events continue; } + const bool ctrl_key_down = (rec.Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED) || + (rec.Event.KeyEvent.dwControlKeyState & RIGHT_CTRL_PRESSED); + const int ret = esc_seq_process_vk(rec.Event.KeyEvent.wVirtualKeyCode, ctrl_key_down); + if (ret) { + return ret; + } const char c = rec.Event.KeyEvent.uChar.AsciiChar; if (c) { // plain ascii char, return it return c; } - const int ret = esc_seq_process_vk(rec.Event.KeyEvent.wVirtualKeyCode); - if (ret) { - return ret; - } } } From fe203bb3e2c98239ece07f340b3e745368636bb8 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 13 Jan 2020 17:10:41 +1100 Subject: [PATCH 0889/1299] py/pairheap: Add generic implementation of pairing heap data structure. --- py/pairheap.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++ py/pairheap.h | 90 ++++++++++++++++++++++++++++++++ py/py.mk | 1 + 3 files changed, 230 insertions(+) create mode 100644 py/pairheap.c create mode 100644 py/pairheap.h diff --git a/py/pairheap.c b/py/pairheap.c new file mode 100644 index 0000000000000..caa51bf797a41 --- /dev/null +++ b/py/pairheap.c @@ -0,0 +1,139 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/pairheap.h" + +// The mp_pairheap_t.next pointer can take one of the following values: +// - NULL: the node is the top of the heap +// - LSB set: the node is the last of the children and points to its parent node +// - other: the node is a child and not the last child +// The macros below help manage this pointer. +#define NEXT_MAKE_RIGHTMOST_PARENT(parent) ((void*)((uintptr_t)(parent) | 1)) +#define NEXT_IS_RIGHTMOST_PARENT(next) ((uintptr_t)(next) & 1) +#define NEXT_GET_RIGHTMOST_PARENT(next) ((void*)((uintptr_t)(next) & ~1)) + +// O(1), stable +mp_pairheap_t *mp_pairheap_meld(mp_pairheap_lt_t lt, mp_pairheap_t *heap1, mp_pairheap_t *heap2) { + if (heap1 == NULL) { + return heap2; + } + if (heap2 == NULL) { + return heap1; + } + if (lt(heap1, heap2)) { + if (heap1->child == NULL) { + heap1->child = heap2; + } else { + heap1->child_last->next = heap2; + } + heap1->child_last = heap2; + heap2->next = NEXT_MAKE_RIGHTMOST_PARENT(heap1); + return heap1; + } else { + heap1->next = heap2->child; + heap2->child = heap1; + if (heap1->next == NULL) { + heap2->child_last = heap1; + heap1->next = NEXT_MAKE_RIGHTMOST_PARENT(heap2); + } + return heap2; + } +} + +// amortised O(log N), stable +mp_pairheap_t *mp_pairheap_pairing(mp_pairheap_lt_t lt, mp_pairheap_t *child) { + if (child == NULL) { + return NULL; + } + mp_pairheap_t *heap = NULL; + while (!NEXT_IS_RIGHTMOST_PARENT(child)) { + mp_pairheap_t *n1 = child; + child = child->next; + if (!NEXT_IS_RIGHTMOST_PARENT(child)) { + mp_pairheap_t *n2 = child; + child = child->next; + n1 = mp_pairheap_meld(lt, n1, n2); + } + heap = mp_pairheap_meld(lt, heap, n1); + } + heap->next = NULL; + return heap; +} + +// amortised O(log N), stable +mp_pairheap_t *mp_pairheap_delete(mp_pairheap_lt_t lt, mp_pairheap_t *heap, mp_pairheap_t *node) { + // Simple case of the top being the node to delete + if (node == heap) { + return mp_pairheap_pairing(lt, heap->child); + } + + // Case where node is not in the heap + if (node->next == NULL) { + return heap; + } + + // Find parent of node + mp_pairheap_t *parent = node; + while (!NEXT_IS_RIGHTMOST_PARENT(parent->next)) { + parent = parent->next; + } + parent = NEXT_GET_RIGHTMOST_PARENT(parent->next); + + // Replace node with pairing of its children + mp_pairheap_t *next; + if (node == parent->child && node->child == NULL) { + if (NEXT_IS_RIGHTMOST_PARENT(node->next)) { + parent->child = NULL; + } else { + parent->child = node->next; + } + node->next = NULL; + return heap; + } else if (node == parent->child) { + next = node->next; + node->next = NULL; + node = mp_pairheap_pairing(lt, node->child); + parent->child = node; + } else { + mp_pairheap_t *n = parent->child; + while (node != n->next) { + n = n->next; + } + next = node->next; + node->next = NULL; + node = mp_pairheap_pairing(lt, node->child); + if (node == NULL) { + node = n; + } else { + n->next = node; + } + } + node->next = next; + if (NEXT_IS_RIGHTMOST_PARENT(next)) { + parent->child_last = node; + } + return heap; +} diff --git a/py/pairheap.h b/py/pairheap.h new file mode 100644 index 0000000000000..f9517f281ebdb --- /dev/null +++ b/py/pairheap.h @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_PY_PAIRHEAP_H +#define MICROPY_INCLUDED_PY_PAIRHEAP_H + +// This is an implementation of a pairing heap. It is stable and has deletion +// support. Only the less-than operation needs to be defined on elements. +// +// See original paper for details: +// Michael L. Fredman, Robert Sedjewick, Daniel D. Sleator, and Robert E. Tarjan. +// The Pairing Heap: A New Form of Self-Adjusting Heap. +// Algorithmica 1:111-129, 1986. +// https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf + +#include "py/obj.h" + +// This struct forms the nodes of the heap and is intended to be extended, by +// placing it first in another struct, to include additional information for the +// element stored in the heap. It includes "base" so it can be a MicroPython +// object allocated on the heap and the GC can automatically trace all nodes by +// following the tree structure. +typedef struct _mp_pairheap_t { + mp_obj_base_t base; + struct _mp_pairheap_t *child; + struct _mp_pairheap_t *child_last; + struct _mp_pairheap_t *next; +} mp_pairheap_t; + +// This is the function for the less-than operation on nodes/elements. +typedef int (*mp_pairheap_lt_t)(mp_pairheap_t*, mp_pairheap_t*); + +// Core functions. +mp_pairheap_t *mp_pairheap_meld(mp_pairheap_lt_t lt, mp_pairheap_t *heap1, mp_pairheap_t *heap2); +mp_pairheap_t *mp_pairheap_pairing(mp_pairheap_lt_t lt, mp_pairheap_t *child); +mp_pairheap_t *mp_pairheap_delete(mp_pairheap_lt_t lt, mp_pairheap_t *heap, mp_pairheap_t *node); + +// Create a new heap. +static inline mp_pairheap_t *mp_pairheap_new(mp_pairheap_lt_t lt) { + (void)lt; + return NULL; +} + +// Test if the heap is empty. +static inline bool mp_pairheap_is_empty(mp_pairheap_lt_t lt, mp_pairheap_t *heap) { + (void)lt; + return heap == NULL; +} + +// Peek at the top of the heap. Will return NULL if empty. +static inline mp_pairheap_t *mp_pairheap_peek(mp_pairheap_lt_t lt, mp_pairheap_t *heap) { + (void)lt; + return heap; +} + +// Push new node onto existing heap. Returns the new heap. +static inline mp_pairheap_t *mp_pairheap_push(mp_pairheap_lt_t lt, mp_pairheap_t *heap, mp_pairheap_t *node) { + node->child = NULL; + node->next = NULL; + return mp_pairheap_meld(lt, node, heap); // node is first to be stable +} + +// Pop the top off the heap, which must not be empty. Returns the new heap. +static inline mp_pairheap_t *mp_pairheap_pop(mp_pairheap_lt_t lt, mp_pairheap_t *heap) { + return mp_pairheap_pairing(lt, heap->child); +} + +#endif // MICROPY_INCLUDED_PY_PAIRHEAP_H diff --git a/py/py.mk b/py/py.mk index 09de1962d3594..1a56dcce8f78a 100644 --- a/py/py.mk +++ b/py/py.mk @@ -94,6 +94,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ runtime_utils.o \ scheduler.o \ nativeglue.o \ + pairheap.o \ ringbuf.o \ stackctrl.o \ argcheck.o \ From f70373c7b255a465300517c41a058909b4d3cea2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 13 Jan 2020 17:12:50 +1100 Subject: [PATCH 0890/1299] stm32/softtimer: Change linear linked list to a pairing heap. --- ports/stm32/machine_timer.c | 2 +- ports/stm32/mpconfigport.h | 2 +- ports/stm32/softtimer.c | 59 ++++++++++++++----------------------- ports/stm32/softtimer.h | 5 ++-- 4 files changed, 26 insertions(+), 42 deletions(-) diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c index 22fa67d7d9d69..1e9be426279a7 100644 --- a/ports/stm32/machine_timer.c +++ b/ports/stm32/machine_timer.c @@ -77,7 +77,7 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_ar STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); - self->base.type = &machine_timer_type; + self->pairheap.base.type = &machine_timer_type; // Get timer id (only soft timer (-1) supported at the moment) mp_int_t id = -1; diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 55f09f81f09f1..2e4fc04061359 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -281,7 +281,7 @@ struct _mp_bluetooth_nimble_root_pointers_t; \ mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ \ - struct _soft_timer_entry_t *soft_timer_head; \ + struct _soft_timer_entry_t *soft_timer_heap; \ \ /* pointers to all Timer objects (if they have been created) */ \ struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \ diff --git a/ports/stm32/softtimer.c b/ports/stm32/softtimer.c index c598bac1779c7..60c2709d93ee8 100644 --- a/ports/stm32/softtimer.c +++ b/ports/stm32/softtimer.c @@ -37,7 +37,13 @@ extern __IO uint32_t uwTick; volatile uint32_t soft_timer_next; void soft_timer_deinit(void) { - MP_STATE_PORT(soft_timer_head) = NULL; + MP_STATE_PORT(soft_timer_heap) = NULL; +} + +STATIC int soft_timer_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { + soft_timer_entry_t *e1 = (soft_timer_entry_t*)n1; + soft_timer_entry_t *e2 = (soft_timer_entry_t*)n2; + return TICKS_DIFF(e1->expiry_ms, e2->expiry_ms) < 0; } STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { @@ -54,59 +60,38 @@ STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { // Must be executed at IRQ_PRI_PENDSV void soft_timer_handler(void) { uint32_t ticks_ms = uwTick; - soft_timer_entry_t *head = MP_STATE_PORT(soft_timer_head); - while (head != NULL && TICKS_DIFF(head->expiry_ms, ticks_ms) <= 0) { - mp_sched_schedule(head->callback, MP_OBJ_FROM_PTR(head)); - if (head->mode == SOFT_TIMER_MODE_PERIODIC) { - head->expiry_ms += head->delta_ms; - // Shift this node along to its new position - soft_timer_entry_t *cur = head; - while (cur->next != NULL && TICKS_DIFF(head->expiry_ms, cur->next->expiry_ms) >= 0) { - cur = cur->next; - } - if (cur != head) { - soft_timer_entry_t *next = head->next; - head->next = cur->next; - cur->next = head; - head = next; - } - } else { - head = head->next; + soft_timer_entry_t *heap = MP_STATE_PORT(soft_timer_heap); + while (heap != NULL && TICKS_DIFF(heap->expiry_ms, ticks_ms) <= 0) { + soft_timer_entry_t *entry = heap; + heap = (soft_timer_entry_t*)mp_pairheap_pop(soft_timer_lt, &heap->pairheap); + mp_sched_schedule(entry->callback, MP_OBJ_FROM_PTR(entry)); + if (entry->mode == SOFT_TIMER_MODE_PERIODIC) { + entry->expiry_ms += entry->delta_ms; + heap = (soft_timer_entry_t*)mp_pairheap_push(soft_timer_lt, &heap->pairheap, &entry->pairheap); } } - MP_STATE_PORT(soft_timer_head) = head; - if (head == NULL) { + MP_STATE_PORT(soft_timer_heap) = heap; + if (heap == NULL) { // No more timers left, set largest delay possible soft_timer_next = uwTick; } else { // Set soft_timer_next so SysTick calls us back at the correct time - soft_timer_schedule_systick(head->expiry_ms); + soft_timer_schedule_systick(heap->expiry_ms); } } void soft_timer_insert(soft_timer_entry_t *entry) { uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t **head_ptr = &MP_STATE_PORT(soft_timer_head); - while (*head_ptr != NULL && TICKS_DIFF(entry->expiry_ms, (*head_ptr)->expiry_ms) >= 0) { - head_ptr = &(*head_ptr)->next; - } - entry->next = *head_ptr; - *head_ptr = entry; - if (head_ptr == &MP_STATE_PORT(soft_timer_head)) { + MP_STATE_PORT(soft_timer_heap) = (soft_timer_entry_t*)mp_pairheap_push(soft_timer_lt, &MP_STATE_PORT(soft_timer_heap)->pairheap, &entry->pairheap); + if (entry == MP_STATE_PORT(soft_timer_heap)) { // This new timer became the earliest one so set soft_timer_next - soft_timer_schedule_systick((*head_ptr)->expiry_ms); + soft_timer_schedule_systick(entry->expiry_ms); } restore_irq_pri(irq_state); } void soft_timer_remove(soft_timer_entry_t *entry) { uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t **cur = &MP_STATE_PORT(soft_timer_head); - while (*cur != NULL) { - if (*cur == entry) { - *cur = entry->next; - break; - } - } + MP_STATE_PORT(soft_timer_heap) = (soft_timer_entry_t*)mp_pairheap_delete(soft_timer_lt, &MP_STATE_PORT(soft_timer_heap)->pairheap, &entry->pairheap); restore_irq_pri(irq_state); } diff --git a/ports/stm32/softtimer.h b/ports/stm32/softtimer.h index 2550446d832e9..a80d9087b57e3 100644 --- a/ports/stm32/softtimer.h +++ b/ports/stm32/softtimer.h @@ -26,14 +26,13 @@ #ifndef MICROPY_INCLUDED_STM32_SOFTTIMER_H #define MICROPY_INCLUDED_STM32_SOFTTIMER_H -#include "py/obj.h" +#include "py/pairheap.h" #define SOFT_TIMER_MODE_ONE_SHOT (1) #define SOFT_TIMER_MODE_PERIODIC (2) typedef struct _soft_timer_entry_t { - mp_obj_base_t base; // so struct can be used as an object and still be traced by GC - struct _soft_timer_entry_t *next; + mp_pairheap_t pairheap; uint32_t mode; uint32_t expiry_ms; uint32_t delta_ms; // for periodic mode From cfddc6a8c773c204bd748124aa7c445cba1d4891 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 13 Jan 2020 17:35:18 +1100 Subject: [PATCH 0891/1299] tests/extmod: Add basic machine.Timer test. --- tests/extmod/machine_timer.py | 37 +++++++++++++++++++++++++++++++ tests/extmod/machine_timer.py.exp | 4 ++++ 2 files changed, 41 insertions(+) create mode 100644 tests/extmod/machine_timer.py create mode 100644 tests/extmod/machine_timer.py.exp diff --git a/tests/extmod/machine_timer.py b/tests/extmod/machine_timer.py new file mode 100644 index 0000000000000..b7e6a280f926d --- /dev/null +++ b/tests/extmod/machine_timer.py @@ -0,0 +1,37 @@ +# test machine.Timer + +try: + import utime, umachine as machine + machine.Timer +except: + print("SKIP") + raise SystemExit + +# create and deinit +t = machine.Timer(freq=1) +t.deinit() + +# deinit again +t.deinit() + +# create 2 and deinit +t = machine.Timer(freq=1) +t2 = machine.Timer(freq=1) +t.deinit() +t2.deinit() + +# create 2 and deinit in different order +t = machine.Timer(freq=1) +t2 = machine.Timer(freq=1) +t2.deinit() +t.deinit() + +# create one-shot timer with callback and wait for it to print (should be just once) +t = machine.Timer(period=1, mode=machine.Timer.ONE_SHOT, callback=lambda t:print('one-shot')) +utime.sleep_ms(5) +t.deinit() + +# create periodic timer with callback and wait for it to print +t = machine.Timer(period=4, mode=machine.Timer.PERIODIC, callback=lambda t:print('periodic')) +utime.sleep_ms(14) +t.deinit() diff --git a/tests/extmod/machine_timer.py.exp b/tests/extmod/machine_timer.py.exp new file mode 100644 index 0000000000000..2dd85ba67d381 --- /dev/null +++ b/tests/extmod/machine_timer.py.exp @@ -0,0 +1,4 @@ +one-shot +periodic +periodic +periodic From dccace6f3fdded89dbf8173eb3882205c419f2fb Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 14 Jan 2020 00:02:01 +1100 Subject: [PATCH 0892/1299] tests/unix: Add coverage tests for pairheap data structure. --- ports/unix/coverage.c | 59 ++++++++++++++++++++++++++++++++ tests/unix/extra_coverage.py.exp | 13 +++++++ 2 files changed, 72 insertions(+) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 6cd84dc301192..233c6211e9157 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -11,6 +11,7 @@ #include "py/emit.h" #include "py/formatfloat.h" #include "py/ringbuf.h" +#include "py/pairheap.h" #include "py/stream.h" #include "py/binary.h" #include "py/bc.h" @@ -139,6 +140,35 @@ STATIC const mp_obj_type_t mp_type_stest_textio2 = { STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte*)"0123456789"}; STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte*)"0123456789"}; +STATIC int pairheap_lt(mp_pairheap_t *a, mp_pairheap_t *b) { + return (uintptr_t)a < (uintptr_t)b; +} + +// ops array contain operations: x>=0 means push(x), x<0 means delete(-x) +STATIC void pairheap_test(size_t nops, int *ops) { + mp_pairheap_t node[8]; + mp_pairheap_t *heap = mp_pairheap_new(pairheap_lt); + printf("create:"); + for (size_t i = 0; i < nops; ++i) { + if (ops[i] >= 0) { + heap = mp_pairheap_push(pairheap_lt, heap, &node[ops[i]]); + } else { + heap = mp_pairheap_delete(pairheap_lt, heap, &node[-ops[i]]); + } + if (mp_pairheap_is_empty(pairheap_lt, heap)) { + mp_printf(&mp_plat_print, " -"); + } else { + mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]);; + } + } + printf("\npop all:"); + while (!mp_pairheap_is_empty(pairheap_lt, heap)) { + mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]);; + heap = mp_pairheap_pop(pairheap_lt, heap); + } + printf("\n"); +} + // function to run extra tests for things that can't be checked by scripts STATIC mp_obj_t extra_coverage(void) { // mp_printf (used by ports that don't have a native printf) @@ -514,6 +544,35 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf)); } + // pairheap + { + mp_printf(&mp_plat_print, "# pairheap\n"); + + // Basic case. + int t0[] = {0, 2, 1, 3}; + pairheap_test(MP_ARRAY_SIZE(t0), t0); + + // All pushed in reverse order. + int t1[] = {7, 6, 5, 4, 3, 2, 1, 0}; + pairheap_test(MP_ARRAY_SIZE(t1), t1); + + // Basic deletion. + int t2[] = {1, -1, -1, 1, 2, -2, 2, 3, -3}; + pairheap_test(MP_ARRAY_SIZE(t2), t2); + + // Deletion of first child that has next node (the -3). + int t3[] = {1, 2, 3, 4, -1, -3}; + pairheap_test(MP_ARRAY_SIZE(t3), t3); + + // Deletion of node that's not first child (the -2). + int t4[] = {1, 2, 3, 4, -2}; + pairheap_test(MP_ARRAY_SIZE(t4), t4); + + // Deletion of node that's not first child and has children (the -3). + int t5[] = {3, 4, 5, 1, 2, -3}; + pairheap_test(MP_ARRAY_SIZE(t5), t5); + } + mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t); s->base.type = &mp_type_stest_fileio; s->buf = NULL; diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 6aa2da31a4a8c..a41f227be700d 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -101,6 +101,19 @@ cc99 22ff -1 -1 +# pairheap +create: 0 0 0 0 +pop all: 0 1 2 3 +create: 7 6 5 4 3 2 1 0 +pop all: 0 1 2 3 4 5 6 7 +create: 1 - - 1 1 1 1 1 1 +pop all: 1 2 +create: 1 1 1 1 2 2 +pop all: 2 4 +create: 1 1 1 1 1 +pop all: 1 3 4 +create: 3 3 3 1 1 1 +pop all: 1 2 4 5 0123456789 b'0123456789' 7300 7300 From a11e3062275685dd80e1202a3dfa5f026d91a7a7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 13 Jan 2020 17:05:46 +1100 Subject: [PATCH 0893/1299] tools: Add metrics.py script to build and compute port sizes/metrics. --- tools/metrics.py | 205 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100755 tools/metrics.py diff --git a/tools/metrics.py b/tools/metrics.py new file mode 100755 index 0000000000000..0cc6db5107f72 --- /dev/null +++ b/tools/metrics.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2020 Damien P. George +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +""" +This script is used to compute metrics, like code size, of the various ports. + +Typical usage is: + + $ ./tools/metrics.py build | tee size0 + + $ git switch new-feature-branch + $ ./tools/metrics.py build | tee size1 + + $ ./tools/metrics.py diff size0 size1 + +Other commands: + + $ ./tools/metrics.py sizes # print all firmware sizes + $ ./tools/metrics.py clean # clean all ports + +""" + +import sys, re, subprocess + +MAKE_FLAGS = ['-j3', 'CFLAGS_EXTRA=-DNDEBUG'] + +class PortData: + def __init__(self, name, dir, output, make_flags=None): + self.name = name + self.dir = dir + self.output = output + self.make_flags = make_flags + +port_data = { + 'b': PortData('bare-arm', 'bare-arm', 'build/firmware.elf'), + 'm': PortData('minimal x86', 'minimal', 'build/firmware.elf'), + 'u': PortData('unix x64', 'unix', 'micropython'), + 'n': PortData('unix nanbox', 'unix', 'micropython-nanbox', 'VARIANT=nanbox'), + 's': PortData('stm32', 'stm32', 'build-PYBV10/firmware.elf', 'BOARD=PYBV10'), + 'c': PortData('cc3200', 'cc3200', 'build/WIPY/release/application.axf', 'BTARGET=application'), + '8': PortData('esp8266', 'esp8266', 'build-GENERIC/firmware.elf'), + '3': PortData('esp32', 'esp32', 'build-GENERIC/application.elf'), + 'r': PortData('nrf', 'nrf', 'build-pca10040/firmware.elf'), + 'd': PortData('samd', 'samd', 'build-ADAFRUIT_ITSYBITSY_M4_EXPRESS/firmware.elf'), +} + +def syscmd(*args): + sys.stdout.flush() + a2 = [] + for a in args: + if isinstance(a, str): + a2.append(a) + elif a: + a2.extend(a) + subprocess.run(a2) + +def parse_port_list(args): + if not args: + return list(port_data.values()) + else: + ports = [] + for arg in args: + for port_char in arg: + try: + ports.append(port_data[port_char]) + except KeyError: + print('unknown port:', port_char) + sys.exit(1) + return ports + +def read_build_log(filename): + data = dict() + lines = [] + found_sizes = False + with open(filename) as f: + for line in f: + line = line.strip() + if line.strip() == 'COMPUTING SIZES': + found_sizes = True + elif found_sizes: + lines.append(line) + is_size_line = False + for line in lines: + if is_size_line: + fields = line.split() + data[fields[-1]] = [int(f) for f in fields[:-2]] + is_size_line = False + else: + is_size_line = line.startswith('text\t ') + return data + +def do_diff(args): + """Compute the difference between firmware sizes.""" + + if len(args) != 2: + print('usage: %s diff ' % sys.argv[0]) + sys.exit(1) + + data1 = read_build_log(args[0]) + data2 = read_build_log(args[1]) + + for key, value1 in data1.items(): + value2 = data2[key] + for port in port_data.values(): + if key == 'ports/{}/{}'.format(port.dir, port.output): + name = port.name + break + data = [v2 - v1 for v1, v2 in zip(value1, value2)] + warn = '' + board = re.search(r'/build-([A-Za-z0-9_]+)/', key) + if board: + board = board.group(1) + else: + board = '' + if name == 'cc3200': + delta = data[0] + percent = 100 * delta / value1[0] + if data[1] != 0: + warn += ' %+u(data)' % data[1] + else: + delta = data[3] + percent = 100 * delta / value1[3] + if data[1] != 0: + warn += ' %+u(data)' % data[1] + if data[2] != 0: + warn += ' %+u(bss)' % data[2] + if warn: + warn = '[incl%s]' % warn + print('%11s: %+5u %+.3f%% %s%s' % (name, delta, percent, board, warn)) + +def do_clean(args): + """Clean ports.""" + + ports = parse_port_list(args) + + print('CLEANING') + for port in ports: + syscmd('make', '-C', 'ports/{}'.format(port.dir), port.make_flags, 'clean') + +def do_build(args): + """Build ports and print firmware sizes.""" + + ports = parse_port_list(args) + + print('BUILDING MPY-CROSS') + syscmd('make', '-C', 'mpy-cross', MAKE_FLAGS) + + print('BUILDING PORTS') + for port in ports: + syscmd('make', '-C', 'ports/{}'.format(port.dir), MAKE_FLAGS, port.make_flags) + + do_sizes(args) + +def do_sizes(args): + """Compute and print sizes of firmware.""" + + ports = parse_port_list(args) + + print('COMPUTING SIZES') + for port in ports: + syscmd('size', 'ports/{}/{}'.format(port.dir, port.output)) + +def main(): + # Get command to execute + if len(sys.argv) == 1: + print('Available commands:') + for cmd in globals(): + if cmd.startswith('do_'): + print(' {:9} {}'.format(cmd[3:], globals()[cmd].__doc__)) + sys.exit(1) + cmd = sys.argv.pop(1) + + # Dispatch to desired command + try: + cmd = globals()['do_{}'.format(cmd)] + except KeyError: + print("{}: unknown command '{}'".format(sys.argv[0], cmd)) + sys.exit(1) + cmd(sys.argv[1:]) + +if __name__ == '__main__': + main() From 6db5cede06dfb580c5e4f6cdeb1796256969b4fb Mon Sep 17 00:00:00 2001 From: c0rejump Date: Tue, 21 Jan 2020 21:30:50 +0100 Subject: [PATCH 0894/1299] tools/pydfu.py: Clean up syntax, update comments and docstrings. Some parts of code have been aligned to increase readability. In general '' instead of "" were used wherever possible to keep the same convention for entire file. Import inspect line has been moved to the top according to hints reported by pep8 tools. A few extra spaces were removed, a few missing spaces were added. Comments have been updated, mostly in "read_dfu_file" function. Some other comments have been capitalized and/or slightly updated. A few docstrings were fixed as well. No real code changes intended. --- tools/pydfu.py | 195 ++++++++++++++++++++++++++----------------------- 1 file changed, 104 insertions(+), 91 deletions(-) diff --git a/tools/pydfu.py b/tools/pydfu.py index 658ce59ae69ac..962ba2b7f0cb2 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -15,6 +15,7 @@ import argparse import collections +import inspect import re import struct import sys @@ -67,7 +68,6 @@ # Python 3 deprecated getargspec in favour of getfullargspec, but # Python 2 doesn't have the latter, so detect which one to use -import inspect getargspec = getattr(inspect, 'getfullargspec', inspect.getargspec) if 'length' in getargspec(usb.util.get_string).args: @@ -82,9 +82,17 @@ def get_string(dev, index): def find_dfu_cfg_descr(descr): if len(descr) == 9 and descr[0] == 9 and descr[1] == _DFU_DESCRIPTOR_TYPE: - nt = collections.namedtuple('CfgDescr', - ['bLength', 'bDescriptorType', 'bmAttributes', - 'wDetachTimeOut', 'wTransferSize', 'bcdDFUVersion']) + nt = collections.namedtuple( + 'CfgDescr', + [ + 'bLength', + 'bDescriptorType', + 'bmAttributes', + 'wDetachTimeOut', + 'wTransferSize', + 'bcdDFUVersion' + ] + ) return nt(*struct.unpack(' 1: - raise ValueError("Multiple DFU devices found") + raise ValueError('Multiple DFU devices found') __dev = devices[0] __dev.set_configuration() @@ -141,57 +149,56 @@ def get_status(): """Get the status of the last operation.""" stat = __dev.ctrl_transfer(0xA1, __DFU_GETSTATUS, 0, __DFU_INTERFACE, 6, 20000) - # print (__DFU_STAT[stat[4]], stat) return stat[4] def mass_erase(): - """Performs a MASS erase (i.e. erases the entire device.""" + """Performs a MASS erase (i.e. erases the entire device).""" # Send DNLOAD with first byte=0x41 __dev.ctrl_transfer(0x21, __DFU_DNLOAD, 0, __DFU_INTERFACE, - "\x41", __TIMEOUT) + '\x41', __TIMEOUT) # Execute last command if get_status() != __DFU_STATE_DFU_DOWNLOAD_BUSY: - raise Exception("DFU: erase failed") + raise Exception('DFU: erase failed') # Check command state if get_status() != __DFU_STATE_DFU_DOWNLOAD_IDLE: - raise Exception("DFU: erase failed") + raise Exception('DFU: erase failed') def page_erase(addr): """Erases a single page.""" if __verbose: - print("Erasing page: 0x%x..." % (addr)) + print('Erasing page: 0x%x...' % (addr)) # Send DNLOAD with first byte=0x41 and page address - buf = struct.pack(" Date: Wed, 22 Jan 2020 11:19:37 -0600 Subject: [PATCH 0895/1299] py/gc: Don't include or init gc_mutex when GIL is enabled. When threads and the GIL are enabled, then the GC mutex is not needed. The gc_mutex field is never used in this case because of: #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL #define GC_ENTER() mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1) #define GC_EXIT() mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex)) #else #define GC_ENTER() #define GC_EXIT() #endif So, we can completely remove gc_mutex everywhere when MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL. --- py/gc.c | 2 +- py/mpstate.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/py/gc.c b/py/gc.c index c763a839ec231..c18cd429f3567 100644 --- a/py/gc.c +++ b/py/gc.c @@ -161,7 +161,7 @@ void gc_init(void *start, void *end) { MP_STATE_MEM(gc_alloc_amount) = 0; #endif - #if MICROPY_PY_THREAD + #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex)); #endif diff --git a/py/mpstate.h b/py/mpstate.h index ab7d8c51b95bc..9bb87f0ba7fb9 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -98,7 +98,7 @@ typedef struct _mp_state_mem_t { size_t gc_collected; #endif - #if MICROPY_PY_THREAD + #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL // This is a global mutex used to make the GC thread-safe. mp_thread_mutex_t gc_mutex; #endif From edbb73a411919af954619dcee02bc448912c9e27 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 22 Jan 2020 11:19:37 -0600 Subject: [PATCH 0896/1299] py/qstr: Don't include or init qstr_mutex when GIL is enabled. When threads and the GIL are enabled, then the qstr mutex is not needed. The qstr_mutex field is never used in this case because of: #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL #define QSTR_ENTER() mp_thread_mutex_lock(&MP_STATE_VM(qstr_mutex), 1) #define QSTR_EXIT() mp_thread_mutex_unlock(&MP_STATE_VM(qstr_mutex)) #else #define QSTR_ENTER() #define QSTR_EXIT() #endif So, we can completely remove qstr_mutex everywhere when MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL. --- py/mpstate.h | 2 +- py/qstr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/py/mpstate.h b/py/mpstate.h index 9bb87f0ba7fb9..5f6cf55936a32 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -203,7 +203,7 @@ typedef struct _mp_state_vm_t { size_t qstr_last_alloc; size_t qstr_last_used; - #if MICROPY_PY_THREAD + #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL // This is a global mutex used to make qstr interning thread-safe. mp_thread_mutex_t qstr_mutex; #endif diff --git a/py/qstr.c b/py/qstr.c index 29ffcae4081b6..940d09ea40661 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -125,7 +125,7 @@ void qstr_init(void) { MP_STATE_VM(last_pool) = (qstr_pool_t*)&CONST_POOL; // we won't modify the const_pool since it has no allocated room left MP_STATE_VM(qstr_last_chunk) = NULL; - #if MICROPY_PY_THREAD + #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(qstr_mutex)); #endif } From edc7a8bf1d984365ef3f6a1ef3e8238fdb813fed Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 23 Jan 2020 13:01:39 +1100 Subject: [PATCH 0897/1299] py/objgenerator: Use mp_obj_new_exception_arg1 to make StopIteration. --- py/objgenerator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/objgenerator.c b/py/objgenerator.c index 903a6469cccd4..8b387d8732e60 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -243,7 +243,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o if (ret == mp_const_none || ret == MP_OBJ_STOP_ITERATION) { return MP_OBJ_STOP_ITERATION; } else { - nlr_raise(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret)); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_StopIteration, ret)); } case MP_VM_RETURN_YIELD: From e2c1226da4ed1498c0373c6a262f0b782600e2fe Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 23 Jan 2020 13:03:00 +1100 Subject: [PATCH 0898/1299] py/objexcept: Optimise mp_obj_new_exception[_arg1/_args] functions. This reduces code size by 10-70 bytes on all ports (except cc3200 which has no change). --- py/objexcept.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/py/objexcept.c b/py/objexcept.c index 869a80bbe783f..33ad74ee7112b 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -304,17 +304,19 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) */ mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) { - return mp_obj_new_exception_args(exc_type, 0, NULL); + assert(exc_type->make_new == mp_obj_exception_make_new); + return mp_obj_exception_make_new(exc_type, 0, 0, NULL); } // "Optimized" version for common(?) case of having 1 exception arg mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { - return mp_obj_new_exception_args(exc_type, 1, &arg); + assert(exc_type->make_new == mp_obj_exception_make_new); + return mp_obj_exception_make_new(exc_type, 1, 0, &arg); } mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args) { assert(exc_type->make_new == mp_obj_exception_make_new); - return exc_type->make_new(exc_type, n_args, 0, args); + return mp_obj_exception_make_new(exc_type, n_args, 0, args); } mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg) { From 27f41e624c39f661f917c20b58daf6637ada0982 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 23 Jan 2020 13:18:34 +1100 Subject: [PATCH 0899/1299] tests/unix: Add coverage test for mp_obj_new_exception_args. Because it's no longer called anywhere in the code. --- ports/unix/coverage.c | 3 +++ tests/unix/extra_coverage.py.exp | 1 + 2 files changed, 4 insertions(+) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 233c6211e9157..e4d2d68fc9765 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -387,6 +387,9 @@ STATIC mp_obj_t extra_coverage(void) { } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } + + // call mp_obj_new_exception_args (it's a part of the public C API and not used in the core) + mp_obj_print_exception(&mp_plat_print, mp_obj_new_exception_args(&mp_type_ValueError, 0, NULL)); } // warning diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index a41f227be700d..9c3b036b930b6 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -58,6 +58,7 @@ TypeError: unsupported types for __divmod__: 'str', 'str' 2 OverflowError: overflow converting long int to machine word OverflowError: overflow converting long int to machine word +ValueError: Warning: test # format float ? From d9433d3e9497a4ec4cd51eb78d6ca602f310ce91 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 22 Jan 2020 13:19:14 +0100 Subject: [PATCH 0900/1299] py/obj.h: Add and use mp_obj_is_bool() helper. Commit d96cfd13e3a464862cecffb2718c6286b52c77b0 introduced a regression in testing for bool objects, that such objects were in some cases no longer recognised and bools, eg when using mp_obj_is_type(o, &mp_type_bool), or mp_obj_is_integer(o). This commit fixes that problem by adding mp_obj_is_bool(o). Builds with MICROPY_OBJ_IMMEDIATE_OBJS enabled check if the object is any of the const True or False objects. Builds without it use the old method of ->type checking, which compiles to smaller code (compared with the former mentioned method). Fixes #5538. --- py/obj.h | 8 +++++++- py/objstr.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/py/obj.h b/py/obj.h index ba4f4992fffab..b052b9fc8b5c2 100644 --- a/py/obj.h +++ b/py/obj.h @@ -665,6 +665,12 @@ extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj; // Note: these are kept as macros because inline functions sometimes use much // more code space than the equivalent macros, depending on the compiler. #define mp_obj_is_type(o, t) (mp_obj_is_obj(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that +#if MICROPY_OBJ_IMMEDIATE_OBJS +// bool's are immediates, not real objects, so test for the 2 possible values. +#define mp_obj_is_bool(o) ((o) == mp_const_false || (o) == mp_const_true) +#else +#define mp_obj_is_bool(o) mp_obj_is_type(o, &mp_type_bool) +#endif #define mp_obj_is_int(o) (mp_obj_is_small_int(o) || mp_obj_is_type(o, &mp_type_int)) #define mp_obj_is_str(o) (mp_obj_is_qstr(o) || mp_obj_is_type(o, &mp_type_str)) #define mp_obj_is_str_or_bytes(o) (mp_obj_is_qstr(o) || (mp_obj_is_obj(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op)) @@ -721,7 +727,7 @@ bool mp_obj_is_true(mp_obj_t arg); bool mp_obj_is_callable(mp_obj_t o_in); bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); -static inline bool mp_obj_is_integer(mp_const_obj_t o) { return mp_obj_is_int(o) || mp_obj_is_type(o, &mp_type_bool); } // returns true if o is bool, small int or long int +static inline bool mp_obj_is_integer(mp_const_obj_t o) { return mp_obj_is_int(o) || mp_obj_is_bool(o); } // returns true if o is bool, small int or long int mp_int_t mp_obj_get_int(mp_const_obj_t arg); mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg); bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value); diff --git a/py/objstr.c b/py/objstr.c index 454d1cbcc5445..7e7e86dddc873 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -910,7 +910,7 @@ STATIC bool istype(char ch) { } STATIC bool arg_looks_integer(mp_obj_t arg) { - return mp_obj_is_type(arg, &mp_type_bool) || mp_obj_is_int(arg); + return mp_obj_is_bool(arg) || mp_obj_is_int(arg); } STATIC bool arg_looks_numeric(mp_obj_t arg) { From 35e664d7790b123dab54faff766f41991f4620d1 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 22 Jan 2020 20:44:52 +0100 Subject: [PATCH 0901/1299] tests/unix: Add coverage tests for mp_obj_is_type() and variants. --- ports/unix/coverage.c | 23 ++++++++++++++++++++++- tests/unix/extra_coverage.py.exp | 8 ++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index e4d2d68fc9765..1b6132cddddc5 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -16,6 +16,8 @@ #include "py/binary.h" #include "py/bc.h" +// expected output of this file is found in extra_coverage.py.exp + #if defined(MICROPY_UNIX_COVERAGE) // stream testing object @@ -539,7 +541,7 @@ STATIC mp_obj_t extra_coverage(void) { ringbuf.iput = 0; ringbuf.iget = 0; mp_printf(&mp_plat_print, "%d\n", ringbuf_get16(&ringbuf)); - + // Two-byte get from ringbuf with one byte available. ringbuf.iput = 0; ringbuf.iget = 0; @@ -576,6 +578,25 @@ STATIC mp_obj_t extra_coverage(void) { pairheap_test(MP_ARRAY_SIZE(t5), t5); } + // mp_obj_is_type and derivatives + { + mp_printf(&mp_plat_print, "# mp_obj_is_type\n"); + + // mp_obj_is_bool accepts only booleans + mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_bool(mp_const_true), mp_obj_is_bool(mp_const_false)); + mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_bool(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_bool(mp_const_none)); + + // mp_obj_is_integer accepts ints and booleans + mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_integer(mp_obj_new_int_from_ll(1))); + mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_const_true), mp_obj_is_integer(mp_const_false)); + mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_obj_new_str("1", 1)), mp_obj_is_integer(mp_const_none)); + + // mp_obj_is_int accepts small int and object ints + mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_int(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_int(mp_obj_new_int_from_ll(1))); + } + + mp_printf(&mp_plat_print, "# end coverage.c\n"); + mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t); s->base.type = &mp_type_stest_fileio; s->buf = NULL; diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index 9c3b036b930b6..6130a06511ef4 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -115,6 +115,14 @@ create: 1 1 1 1 1 pop all: 1 3 4 create: 3 3 3 1 1 1 pop all: 1 2 4 5 +# mp_obj_is_type +1 1 +0 0 +1 1 +1 1 +0 0 +1 1 +# end coverage.c 0123456789 b'0123456789' 7300 7300 From cb4472df42e6f34df2fe57f4f85786f6669171f7 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 22 Jan 2020 20:53:54 +0100 Subject: [PATCH 0902/1299] tests: Add boolean-as-integer formatting tests for fixed regression. As suggested by @dpgeorge in #5538. --- tests/basics/string_format.py | 6 ++++++ tests/basics/string_format_modulo.py | 3 +++ tests/float/string_format.py | 3 +++ 3 files changed, 12 insertions(+) diff --git a/tests/basics/string_format.py b/tests/basics/string_format.py index 8b2592406737f..e8600f5836139 100644 --- a/tests/basics/string_format.py +++ b/tests/basics/string_format.py @@ -63,6 +63,12 @@ def test(fmt, *args): test("{:^20}", "foo") test("{:<20}", "foo") +# formatting bool as int +test('{:d}', False) +test('{:20}', False) +test('{:d}', True) +test('{:20}', True) + # nested format specifiers print("{:{}}".format(123, '#>10')) print("{:{}{}{}}".format(123, '#', '>', '10')) diff --git a/tests/basics/string_format_modulo.py b/tests/basics/string_format_modulo.py index 021b5f08d2849..01f8e7ed24059 100644 --- a/tests/basics/string_format_modulo.py +++ b/tests/basics/string_format_modulo.py @@ -40,6 +40,9 @@ print("%10s" % 'abc') print("%-10s" % 'abc') +print('%c' % False) +print('%c' % True) + # Should be able to print dicts; in this case they aren't used # to lookup keywords in formats like %(foo)s print('%s' % {}) diff --git a/tests/float/string_format.py b/tests/float/string_format.py index 6fb11c35acaba..54f12707732ea 100644 --- a/tests/float/string_format.py +++ b/tests/float/string_format.py @@ -24,6 +24,9 @@ def test(fmt, *args): test("{:06e}", float("-inf")) test("{:06e}", float("nan")) +test('{:f}', False) +test('{:f}', True) + # The following fails right now #test("{:10.1}", 0.0) From 96716b46e1c4945d3fe08d9ba91920ca28f9c986 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 24 Jan 2020 11:51:21 +1100 Subject: [PATCH 0903/1299] unix/Makefile: Reserve CFLAGS_EXTRA/LDFLAGS_EXTRA for external use. When CFLAGS_EXTRA/LDFLAGS_EXTRA (or anything) is set on the command line of a make invocation then it will completely override any setting or appending of these variables in the makefile(s). This means builds like the coverage variant will have their mpconfigvariant.mk settings overridden. Fix this by using CFLAGS/LDFLAGS exclusively in the makefile(s), reserving the CFLAGS_EXTRA/LDFLAGS_EXTRA variables for external command-line use only. --- ports/unix/Makefile | 4 ++-- ports/unix/variants/coverage/mpconfigvariant.mk | 4 ++-- ports/unix/variants/freedos/mpconfigvariant.mk | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 567b1d5c22c2c..23ea6d1fe5c3f 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -40,7 +40,7 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror CWARN += -Wpointer-arith -Wuninitialized -CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) +CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) # Debugging/Optimization ifdef DEBUG @@ -91,7 +91,7 @@ else # Use gcc syntax for map file LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif -LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) +LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) # Flags to link with pthread library LIBPTHREAD = -lpthread diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index 077e7e11ac022..056a5fd3f1477 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -2,13 +2,13 @@ PROG ?= micropython-coverage COPT = -O0 -CFLAGS_EXTRA += \ +CFLAGS += \ -fprofile-arcs -ftest-coverage \ -Wdouble-promotion -Wformat -Wmissing-declarations -Wmissing-prototypes -Wsign-compare \ -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ -DMICROPY_UNIX_COVERAGE -LDFLAGS_EXTRA += -fprofile-arcs -ftest-coverage +LDFLAGS += -fprofile-arcs -ftest-coverage FROZEN_MANIFEST = manifest_coverage.py diff --git a/ports/unix/variants/freedos/mpconfigvariant.mk b/ports/unix/variants/freedos/mpconfigvariant.mk index f7e5ed5162c83..a30db3e0c1490 100644 --- a/ports/unix/variants/freedos/mpconfigvariant.mk +++ b/ports/unix/variants/freedos/mpconfigvariant.mk @@ -4,7 +4,7 @@ STRIP = i586-pc-msdosdjgpp-strip SIZE = i586-pc-msdosdjgpp-size -CFLAGS_EXTRA = \ +CFLAGS += \ -DMICROPY_NLR_SETJMP \ -Dtgamma=gamma \ -DMICROPY_EMIT_X86=0 \ From fee7e5617f55b4778de74ee185fcc3950cdc7b6d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 22 Jan 2020 18:14:03 -0600 Subject: [PATCH 0904/1299] unix: Release GIL during all system calls. Addition of GIL EXIT/ENTER pairs are: - modos: release the GIL during system calls. CPython does this as well. - moduselect: release the GIL during the poll() syscall. This call can be blocking, so it is important to allow other threads to run at this time. - modusocket: release the GIL during system calls. Many of these calls can be blocking, so it is important to allow other threads to run. - unix_mphal: release the GIL during the read and write syscalls in mp_hal_stdin_rx_chr and mp_hal_stdout_tx_strn. If we don't do this threads are blocked when the REPL or the builtin input function are used. - file, main, mpconfigport.h: release GIL during syscalls in built-in functions that could block. --- ports/unix/file.c | 18 +++++++++++++++- ports/unix/main.c | 2 ++ ports/unix/modos.c | 20 ++++++++++++++++++ ports/unix/moduselect.c | 3 +++ ports/unix/modusocket.c | 43 +++++++++++++++++++++++++++++++++++++-- ports/unix/mpconfigport.h | 7 ++++++- ports/unix/unix_mphal.c | 5 +++++ 7 files changed, 94 insertions(+), 4 deletions(-) diff --git a/ports/unix/file.c b/ports/unix/file.c index 6c6e26b0b290c..8a165283f710b 100644 --- a/ports/unix/file.c +++ b/ports/unix/file.c @@ -35,6 +35,7 @@ #include "py/stream.h" #include "py/builtin.h" #include "py/mphal.h" +#include "py/mpthread.h" #include "fdfile.h" #if MICROPY_PY_IO && !MICROPY_VFS @@ -65,7 +66,9 @@ STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); + MP_THREAD_GIL_EXIT(); mp_int_t r = read(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); if (r == -1) { *errcode = errno; return MP_STREAM_ERROR; @@ -82,14 +85,18 @@ STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in return size; } #endif + MP_THREAD_GIL_EXIT(); mp_int_t r = write(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); while (r == -1 && errno == EINTR) { if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } + MP_THREAD_GIL_EXIT(); r = write(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); } if (r == -1) { *errcode = errno; @@ -104,7 +111,9 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i switch (request) { case MP_STREAM_SEEK: { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg; + MP_THREAD_GIL_EXIT(); off_t off = lseek(o->fd, s->offset, s->whence); + MP_THREAD_GIL_ENTER(); if (off == (off_t)-1) { *errcode = errno; return MP_STREAM_ERROR; @@ -113,13 +122,18 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i return 0; } case MP_STREAM_FLUSH: - if (fsync(o->fd) < 0) { + MP_THREAD_GIL_EXIT(); + int ret = fsync(o->fd); + MP_THREAD_GIL_ENTER(); + if (ret == -1) { *errcode = errno; return MP_STREAM_ERROR; } return 0; case MP_STREAM_CLOSE: + MP_THREAD_GIL_EXIT(); close(o->fd); + MP_THREAD_GIL_ENTER(); #ifdef MICROPY_CPYTHON_COMPAT o->fd = -1; #endif @@ -198,7 +212,9 @@ STATIC mp_obj_t fdfile_open(const mp_obj_type_t *type, mp_arg_val_t *args) { } const char *fname = mp_obj_str_get_str(fid); + MP_THREAD_GIL_EXIT(); int fd = open(fname, mode_x | mode_rw, 0644); + MP_THREAD_GIL_ENTER(); if (fd == -1) { mp_raise_OSError(errno); } diff --git a/ports/unix/main.c b/ports/unix/main.c index 9147feb32d9c3..fcf8b1558c613 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -64,7 +64,9 @@ long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4); STATIC void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; + MP_THREAD_GIL_EXIT(); ssize_t dummy = write(STDERR_FILENO, str, len); + MP_THREAD_GIL_ENTER(); mp_uos_dupterm_tx_strn(str, len); (void)dummy; } diff --git a/ports/unix/modos.c b/ports/unix/modos.c index c3b0c20b2b007..e5bd5da1eb33b 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -38,6 +38,7 @@ #include "py/runtime.h" #include "py/objtuple.h" #include "py/mphal.h" +#include "py/mpthread.h" #include "extmod/vfs.h" #include "extmod/misc.h" @@ -49,7 +50,9 @@ STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) { struct stat sb; const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); int res = stat(path, &sb); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(res, errno); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); @@ -89,7 +92,9 @@ STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) { STRUCT_STATVFS sb; const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); int res = STATVFS(path, &sb); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(res, errno); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); @@ -116,7 +121,9 @@ STATIC mp_obj_t mod_os_remove(mp_obj_t path_in) { // of that function. But Python remove() follows ANSI C, and explicitly // required to raise exception on attempt to remove a directory. Thus, // call POSIX unlink() here. + MP_THREAD_GIL_EXIT(); int r = unlink(path); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -128,7 +135,9 @@ STATIC mp_obj_t mod_os_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) { const char *old_path = mp_obj_str_get_str(old_path_in); const char *new_path = mp_obj_str_get_str(new_path_in); + MP_THREAD_GIL_EXIT(); int r = rename(old_path, new_path); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -139,7 +148,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_os_rename_obj, mod_os_rename); STATIC mp_obj_t mod_os_rmdir(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); int r = rmdir(path); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -150,7 +161,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_rmdir_obj, mod_os_rmdir); STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { const char *cmd = mp_obj_str_get_str(cmd_in); + MP_THREAD_GIL_EXIT(); int r = system(cmd); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -170,11 +183,13 @@ MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_obj, mod_os_getenv); STATIC mp_obj_t mod_os_mkdir(mp_obj_t path_in) { // TODO: Accept mode param const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); #ifdef _WIN32 int r = mkdir(path); #else int r = mkdir(path, 0777); #endif + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -192,13 +207,16 @@ STATIC mp_obj_t listdir_next(mp_obj_t self_in) { if (self->dir == NULL) { goto done; } + MP_THREAD_GIL_EXIT(); struct dirent *dirent = readdir(self->dir); if (dirent == NULL) { closedir(self->dir); + MP_THREAD_GIL_ENTER(); self->dir = NULL; done: return MP_OBJ_STOP_ITERATION; } + MP_THREAD_GIL_ENTER(); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); t->items[0] = mp_obj_new_str(dirent->d_name, strlen(dirent->d_name)); @@ -235,7 +253,9 @@ STATIC mp_obj_t mod_os_ilistdir(size_t n_args, const mp_obj_t *args) { } mp_obj_listdir_t *o = m_new_obj(mp_obj_listdir_t); o->base.type = &mp_type_polymorph_iter; + MP_THREAD_GIL_EXIT(); o->dir = opendir(path); + MP_THREAD_GIL_ENTER(); o->iternext = listdir_next; return MP_OBJ_FROM_PTR(o); } diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c index d9b02ddc62cef..4a095ec292c7c 100644 --- a/ports/unix/moduselect.c +++ b/ports/unix/moduselect.c @@ -39,6 +39,7 @@ #include "py/objlist.h" #include "py/objtuple.h" #include "py/mphal.h" +#include "py/mpthread.h" #include "fdfile.h" #define DEBUG 0 @@ -188,7 +189,9 @@ STATIC int poll_poll_internal(size_t n_args, const mp_obj_t *args) { self->flags = flags; + MP_THREAD_GIL_EXIT(); int n_ready = poll(self->entries, self->len, timeout); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(n_ready, errno); return n_ready; } diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 9b82378bb4b35..b436ddf7fc7f6 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -45,6 +45,7 @@ #include "py/stream.h" #include "py/builtin.h" #include "py/mphal.h" +#include "py/mpthread.h" /* The idea of this module is to implement reasonable minimum of @@ -93,7 +94,9 @@ STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); + MP_THREAD_GIL_EXIT(); mp_int_t r = read(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); if (r == -1) { int err = errno; // On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO @@ -110,7 +113,9 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); + MP_THREAD_GIL_EXIT(); mp_int_t r = write(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); if (r == -1) { int err = errno; // On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO @@ -137,7 +142,9 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i // The rationale MicroPython follows is that close() just releases // file descriptor. If you're interested to catch I/O errors before // closing fd, fsync() it. + MP_THREAD_GIL_EXIT(); close(self->fd); + MP_THREAD_GIL_ENTER(); return 0; case MP_STREAM_GET_FILENO: @@ -159,7 +166,9 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); + MP_THREAD_GIL_ENTER(); int err = errno; if (r == -1 && self->blocking && err == EINPROGRESS) { // EINPROGRESS on a blocking socket means the operation timed out @@ -174,7 +183,9 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -182,7 +193,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); + MP_THREAD_GIL_EXIT(); int r = listen(self->fd, MP_OBJ_SMALL_INT_VALUE(backlog_in)); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -194,7 +207,9 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { //struct sockaddr_storage addr; byte addr[32]; socklen_t addr_len = sizeof(addr); + MP_THREAD_GIL_EXIT(); int fd = accept(self->fd, (struct sockaddr*)&addr, &addr_len); + MP_THREAD_GIL_ENTER(); int err = errno; if (fd == -1 && self->blocking && err == EAGAIN) { // EAGAIN on a blocking socket means the operation timed out @@ -223,7 +238,9 @@ STATIC mp_obj_t socket_recv(size_t n_args, const mp_obj_t *args) { } byte *buf = m_new(byte, sz); + MP_THREAD_GIL_EXIT(); int out_sz = recv(self->fd, buf, sz, flags); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); mp_obj_t ret = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); @@ -245,7 +262,9 @@ STATIC mp_obj_t socket_recvfrom(size_t n_args, const mp_obj_t *args) { socklen_t addr_len = sizeof(addr); byte *buf = m_new(byte, sz); + MP_THREAD_GIL_EXIT(); int out_sz = recvfrom(self->fd, buf, sz, flags, (struct sockaddr*)&addr, &addr_len); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); @@ -272,7 +291,9 @@ STATIC mp_obj_t socket_send(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int out_sz = send(self->fd, bufinfo.buf, bufinfo.len, flags); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); return MP_OBJ_NEW_SMALL_INT(out_sz); @@ -292,8 +313,10 @@ STATIC mp_obj_t socket_sendto(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo, addr_bi; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(dst_addr, &addr_bi, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int out_sz = sendto(self->fd, bufinfo.buf, bufinfo.len, flags, (struct sockaddr *)addr_bi.buf, addr_bi.len); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); return MP_OBJ_NEW_SMALL_INT(out_sz); @@ -319,7 +342,9 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { optval = bufinfo.buf; optlen = bufinfo.len; } + MP_THREAD_GIL_EXIT(); int r = setsockopt(self->fd, level, option, optval, optlen); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -328,14 +353,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_s STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); int val = mp_obj_is_true(flag_in); + MP_THREAD_GIL_EXIT(); int flags = fcntl(self->fd, F_GETFL, 0); - RAISE_ERRNO(flags, errno); + if (flags == -1) { + MP_THREAD_GIL_ENTER(); + RAISE_ERRNO(flags, errno); + } if (val) { flags &= ~O_NONBLOCK; } else { flags |= O_NONBLOCK; } flags = fcntl(self->fd, F_SETFL, flags); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(flags, errno); self->blocking = val; return mp_const_none; @@ -368,9 +398,14 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { if (new_blocking) { int r; + MP_THREAD_GIL_EXIT(); r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); - RAISE_ERRNO(r, errno); + if (r == -1) { + MP_THREAD_GIL_ENTER(); + RAISE_ERRNO(r, errno); + } r = setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); } @@ -415,7 +450,9 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz } } + MP_THREAD_GIL_EXIT(); int fd = socket(family, type, proto); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(fd, errno); return MP_OBJ_FROM_PTR(socket_new(fd)); } @@ -537,7 +574,9 @@ STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { } struct addrinfo *addr_list; + MP_THREAD_GIL_EXIT(); int res = getaddrinfo(host, serv, &hints, &addr_list); + MP_THREAD_GIL_ENTER(); if (res != 0) { // CPython: socket.gaierror diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index f435c3ff3c730..2f01aff0f9c89 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -285,7 +285,12 @@ void mp_unix_mark_exec(void); #if MICROPY_PY_OS_DUPTERM #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #else -#define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0) +#define MP_PLAT_PRINT_STRN(str, len) do { \ + MP_THREAD_GIL_EXIT(); \ + ssize_t ret = write(1, str, len); \ + MP_THREAD_GIL_ENTER(); \ + (void)ret; \ +} while (0) #endif #ifdef __linux__ diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 9b009dc5021e1..3e14409efb6ba 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -31,6 +31,7 @@ #include #include "py/mphal.h" +#include "py/mpthread.h" #include "py/runtime.h" #include "extmod/misc.h" @@ -160,7 +161,9 @@ int mp_hal_stdin_rx_chr(void) { } else { main_term:; #endif + MP_THREAD_GIL_EXIT(); int ret = read(0, &c, 1); + MP_THREAD_GIL_ENTER(); if (ret == 0) { c = 4; // EOF, ctrl-D } else if (c == '\n') { @@ -173,7 +176,9 @@ int mp_hal_stdin_rx_chr(void) { } void mp_hal_stdout_tx_strn(const char *str, size_t len) { + MP_THREAD_GIL_EXIT(); int ret = write(1, str, len); + MP_THREAD_GIL_ENTER(); mp_uos_dupterm_tx_strn(str, len); (void)ret; // to suppress compiler warning } From 35f66d38b8e153399b5d277b6e02ea1a98eccee1 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 23 Jan 2020 21:50:53 -0600 Subject: [PATCH 0905/1299] extmod/vfs_posix: Release GIL during system calls. This releases the GIL during syscalls that could block. --- extmod/vfs_posix.c | 20 ++++++++++++++++++-- extmod/vfs_posix_file.c | 16 +++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index d943e0c80371d..22471e48f354c 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -26,6 +26,7 @@ #include "py/runtime.h" #include "py/mperrno.h" +#include "py/mpthread.h" #include "extmod/vfs.h" #include "extmod/vfs_posix.h" @@ -170,12 +171,15 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { } for (;;) { + MP_THREAD_GIL_EXIT(); struct dirent *dirent = readdir(self->dir); if (dirent == NULL) { closedir(self->dir); + MP_THREAD_GIL_ENTER(); self->dir = NULL; return MP_OBJ_STOP_ITERATION; } + MP_THREAD_GIL_ENTER(); const char *fn = dirent->d_name; if (fn[0] == '.' && (fn[1] == 0 || fn[1] == '.')) { @@ -229,7 +233,9 @@ STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { if (path[0] == '\0') { path = "."; } + MP_THREAD_GIL_EXIT(); iter->dir = opendir(path); + MP_THREAD_GIL_ENTER(); if (iter->dir == NULL) { mp_raise_OSError(errno); } @@ -245,7 +251,10 @@ typedef struct _mp_obj_listdir_t { STATIC mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); - int ret = mkdir(vfs_posix_get_path_str(self, path_in), 0777); + const char *path = vfs_posix_get_path_str(self, path_in); + MP_THREAD_GIL_EXIT(); + int ret = mkdir(path, 0777); + MP_THREAD_GIL_ENTER(); if (ret != 0) { mp_raise_OSError(errno); } @@ -262,7 +271,9 @@ STATIC mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_ mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *old_path = vfs_posix_get_path_str(self, old_path_in); const char *new_path = vfs_posix_get_path_str(self, new_path_in); + MP_THREAD_GIL_EXIT(); int ret = rename(old_path, new_path); + MP_THREAD_GIL_ENTER(); if (ret != 0) { mp_raise_OSError(errno); } @@ -278,7 +289,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_rmdir_obj, vfs_posix_rmdir); STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); struct stat sb; - int ret = stat(vfs_posix_get_path_str(self, path_in), &sb); + const char *path = vfs_posix_get_path_str(self, path_in); + MP_THREAD_GIL_EXIT(); + int ret = stat(path, &sb); + MP_THREAD_GIL_ENTER(); if (ret != 0) { mp_raise_OSError(errno); } @@ -321,7 +335,9 @@ STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); STRUCT_STATVFS sb; const char *path = vfs_posix_get_path_str(self, path_in); + MP_THREAD_GIL_EXIT(); int ret = STATVFS(path, &sb); + MP_THREAD_GIL_ENTER(); if (ret != 0) { mp_raise_OSError(errno); } diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 87c202e3b0a65..c817e51b8b469 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include "py/mpthread.h" #include "py/runtime.h" #include "py/stream.h" #include "extmod/vfs_posix.h" @@ -100,7 +101,9 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ } const char *fname = mp_obj_str_get_str(fid); + MP_THREAD_GIL_EXIT(); int fd = open(fname, mode_x | mode_rw, 0644); + MP_THREAD_GIL_ENTER(); if (fd == -1) { mp_raise_OSError(errno); } @@ -135,7 +138,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vfs_posix_file___exit___obj, 4, 4, vf STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); + MP_THREAD_GIL_EXIT(); mp_int_t r = read(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); if (r == -1) { *errcode = errno; return MP_STREAM_ERROR; @@ -159,7 +164,9 @@ STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } + MP_THREAD_GIL_EXIT(); r = write(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); } if (r == -1) { *errcode = errno; @@ -173,14 +180,19 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ check_fd_is_open(o); switch (request) { case MP_STREAM_FLUSH: - if (fsync(o->fd) < 0) { + MP_THREAD_GIL_EXIT(); + int ret = fsync(o->fd); + MP_THREAD_GIL_ENTER(); + if (ret == -1) { *errcode = errno; return MP_STREAM_ERROR; } return 0; case MP_STREAM_SEEK: { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg; + MP_THREAD_GIL_EXIT(); off_t off = lseek(o->fd, s->offset, s->whence); + MP_THREAD_GIL_ENTER(); if (off == (off_t)-1) { *errcode = errno; return MP_STREAM_ERROR; @@ -189,7 +201,9 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ return 0; } case MP_STREAM_CLOSE: + MP_THREAD_GIL_EXIT(); close(o->fd); + MP_THREAD_GIL_ENTER(); #ifdef MICROPY_CPYTHON_COMPAT o->fd = -1; #endif From 62537a18e3743a040e8b673686665f27f7504ca8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 24 Jan 2020 11:50:31 -0600 Subject: [PATCH 0906/1299] py: Release GIL during syscalls in reader and writer code. This releases the GIL during POSIX system calls that could block. --- py/persistentcode.c | 7 +++++++ py/reader.c | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/py/persistentcode.c b/py/persistentcode.c index 7a8a94b5a64a2..7039f9f57a3c6 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -34,6 +34,7 @@ #include "py/persistentcode.h" #include "py/bc0.h" #include "py/objstr.h" +#include "py/mpthread.h" #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE @@ -821,15 +822,21 @@ void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) { STATIC void fd_print_strn(void *env, const char *str, size_t len) { int fd = (intptr_t)env; + MP_THREAD_GIL_EXIT(); ssize_t ret = write(fd, str, len); + MP_THREAD_GIL_ENTER(); (void)ret; } void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename) { + MP_THREAD_GIL_EXIT(); int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + MP_THREAD_GIL_ENTER(); mp_print_t fd_print = {(void*)(intptr_t)fd, fd_print_strn}; mp_raw_code_save(rc, &fd_print); + MP_THREAD_GIL_EXIT(); close(fd); + MP_THREAD_GIL_ENTER(); } #else diff --git a/py/reader.c b/py/reader.c index 80364104bb12b..d99dfc5672adf 100644 --- a/py/reader.c +++ b/py/reader.c @@ -29,6 +29,7 @@ #include "py/runtime.h" #include "py/mperrno.h" +#include "py/mpthread.h" #include "py/reader.h" typedef struct _mp_reader_mem_t { @@ -86,7 +87,9 @@ STATIC mp_uint_t mp_reader_posix_readbyte(void *data) { if (reader->len == 0) { return MP_READER_EOF; } else { + MP_THREAD_GIL_EXIT(); int n = read(reader->fd, reader->buf, sizeof(reader->buf)); + MP_THREAD_GIL_ENTER(); if (n <= 0) { reader->len = 0; return MP_READER_EOF; @@ -101,7 +104,9 @@ STATIC mp_uint_t mp_reader_posix_readbyte(void *data) { STATIC void mp_reader_posix_close(void *data) { mp_reader_posix_t *reader = (mp_reader_posix_t*)data; if (reader->close_fd) { + MP_THREAD_GIL_EXIT(); close(reader->fd); + MP_THREAD_GIL_ENTER(); } m_del_obj(mp_reader_posix_t, reader); } @@ -110,13 +115,16 @@ void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) { mp_reader_posix_t *rp = m_new_obj(mp_reader_posix_t); rp->close_fd = close_fd; rp->fd = fd; + MP_THREAD_GIL_EXIT(); int n = read(rp->fd, rp->buf, sizeof(rp->buf)); if (n == -1) { if (close_fd) { close(fd); } + MP_THREAD_GIL_ENTER(); mp_raise_OSError(errno); } + MP_THREAD_GIL_ENTER(); rp->len = n; rp->pos = 0; reader->data = rp; @@ -127,7 +135,9 @@ void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) { #if !MICROPY_VFS_POSIX // If MICROPY_VFS_POSIX is defined then this function is provided by the VFS layer void mp_reader_new_file(mp_reader_t *reader, const char *filename) { + MP_THREAD_GIL_EXIT(); int fd = open(filename, O_RDONLY, 0644); + MP_THREAD_GIL_ENTER(); if (fd < 0) { mp_raise_OSError(errno); } From bc3499f0103abcae39ad048bb42a518a665b8497 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 24 Jan 2020 11:50:31 -0600 Subject: [PATCH 0907/1299] windows/windows_mphal: Release GIL during system calls. This releases the GIL during syscalls that could block. --- ports/windows/windows_mphal.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ports/windows/windows_mphal.c b/ports/windows/windows_mphal.c index 1ec8e27d6aea8..6de888085fccc 100644 --- a/ports/windows/windows_mphal.c +++ b/ports/windows/windows_mphal.c @@ -27,6 +27,7 @@ #include "py/mpstate.h" #include "py/mphal.h" +#include "py/mpthread.h" #include #include @@ -194,10 +195,14 @@ int mp_hal_stdin_rx_chr(void) { // poll until key which we handle is pressed assure_stdin_handle(); + BOOL status; DWORD num_read; INPUT_RECORD rec; for (;;) { - if (!ReadConsoleInput(std_in, &rec, 1, &num_read) || !num_read) { + MP_THREAD_GIL_EXIT(); + status = ReadConsoleInput(std_in, &rec, 1, &num_read) + MP_THREAD_GIL_ENTER(); + if (!status || !num_read) { return CHAR_CTRL_C; // EOF, ctrl-D } if (rec.EventType != KEY_EVENT || !rec.Event.KeyEvent.bKeyDown) { // only want key down events @@ -217,7 +222,9 @@ int mp_hal_stdin_rx_chr(void) { } void mp_hal_stdout_tx_strn(const char *str, size_t len) { + MP_THREAD_GIL_EXIT(); write(1, str, len); + MP_THREAD_GIL_ENTER(); } void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { From d89ed3e62b152174c3eb5c96713e9b983b11f7ed Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 23 Jan 2020 14:11:13 -0600 Subject: [PATCH 0908/1299] unix/unix_mphal: Add compile check for incompatible GIL+ASYNC_KBD_INTR. It is not safe to enable MICROPY_ASYNC_KBD_INTR and MICROPY_PY_THREAD_GIL at the same time. This will trigger a compiler error to ensure that it is not possible to make this mistake. --- ports/unix/unix_mphal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 3e14409efb6ba..25d1b022db88b 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -41,6 +41,11 @@ STATIC void sighandler(int signum) { if (signum == SIGINT) { #if MICROPY_ASYNC_KBD_INTR + #if MICROPY_PY_THREAD_GIL + // Since signals can occur at any time, we may not be holding the GIL when + // this callback is called, so it is not safe to raise an exception here + #error "MICROPY_ASYNC_KBD_INTR and MICROPY_PY_THREAD_GIL are not compatible" + #endif mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); sigset_t mask; sigemptyset(&mask); From 1f4b607116ea0f06111847510ba5b1cd8080bf7f Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 24 Jan 2020 18:07:32 +1100 Subject: [PATCH 0909/1299] tests: Add tests for generator throw and yield-from with exc handlers. This commit adds a generator test for throwing into a nested exception, and one when using yield-from with a pending exception cleanup. Both these tests currently fail on the native emitter, and are simplified versions of native test failures from uasyncio in #5332. --- tests/basics/gen_yield_from_pending.py | 23 ++++++++++++++++++ tests/basics/generator_throw_nested.py | 33 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/basics/gen_yield_from_pending.py create mode 100644 tests/basics/generator_throw_nested.py diff --git a/tests/basics/gen_yield_from_pending.py b/tests/basics/gen_yield_from_pending.py new file mode 100644 index 0000000000000..eb88ee6ca781a --- /dev/null +++ b/tests/basics/gen_yield_from_pending.py @@ -0,0 +1,23 @@ +# Tests that the pending exception state is managed correctly +# (previously failed on native emitter). + +def noop_task(): + print('noop task') + yield 1 + +def raise_task(): + print('raise task') + yield 2 + print('raising') + raise Exception + +def main(): + try: + yield from raise_task() + except: + print('main exception') + + yield from noop_task() + +for z in main(): + print('outer iter', z) diff --git a/tests/basics/generator_throw_nested.py b/tests/basics/generator_throw_nested.py new file mode 100644 index 0000000000000..5ef166878836c --- /dev/null +++ b/tests/basics/generator_throw_nested.py @@ -0,0 +1,33 @@ +# Tests that the correct nested exception handler is used when +# throwing into a generator (previously failed on native emitter). + +def gen(): + try: + yield 1 + try: + yield 2 + try: + yield 3 + except Exception: + yield 4 + print(0) + yield 5 + except Exception: + yield 6 + print(1) + yield 7 + except Exception: + yield 8 + print(2) + yield 9 + +for i in range(1, 10): + g = gen() + try: + for _ in range(i): + print(next(g)) + print(g.throw(ValueError)) + except ValueError: + print('ValueError') + except StopIteration: + print('StopIteration') From 0de304e7dabbee443dd96935a8045a227eba455b Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 24 Jan 2020 18:01:20 +1100 Subject: [PATCH 0910/1299] py/emitnative: Use NULL for pending exception (not None). This previously made the native emitter incompatible with the bytecode emitter, and mp_resume (and subsequently mp_obj_generator_resume) expects the bytecode emitter behavior (i.e. throw==NULL). --- py/emitnative.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/py/emitnative.c b/py/emitnative.c index 07b984b780f70..0affbeb0b2747 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -2058,7 +2058,7 @@ STATIC void emit_native_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t exc ASM_MOV_REG_PCREL(emit->as, REG_RET, label & ~MP_EMIT_BREAK_FROM_FOR); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_RET); // Cancel any active exception (see also emit_native_pop_except_jump) - emit_native_mov_reg_const(emit, REG_RET, MP_F_CONST_NONE_OBJ); + ASM_MOV_REG_IMM(emit->as, REG_RET, (mp_uint_t)MP_OBJ_NULL); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_RET); // Jump to the innermost active finally label = first_finally->label; @@ -2153,9 +2153,8 @@ STATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); // get exc - // Check if exc is None and jump to non-exc handler if it is - emit_native_mov_reg_const(emit, REG_ARG_2, MP_F_CONST_NONE_OBJ); - ASM_JUMP_IF_REG_EQ(emit->as, REG_ARG_1, REG_ARG_2, *emit->label_slot + 2); + // Check if exc is MP_OBJ_NULL (i.e. zero) and jump to non-exc handler if it is + ASM_JUMP_IF_REG_ZERO(emit->as, REG_ARG_1, *emit->label_slot + 2, false); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_ARG_2, REG_ARG_1, 0); // get type(exc) emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_2); // push type(exc) @@ -2175,9 +2174,9 @@ STATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { emit_call(emit, MP_F_OBJ_IS_TRUE); ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, *emit->label_slot + 1, true); - // Replace exception with None + // Replace exception with MP_OBJ_NULL. emit_native_label_assign(emit, *emit->label_slot); - emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ); + ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); // end of with cleanup nlr_catch block @@ -2255,7 +2254,7 @@ STATIC void emit_native_for_iter_end(emit_t *emit) { STATIC void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { if (within_exc_handler) { // Cancel any active exception so subsequent handlers don't see it - emit_native_mov_reg_const(emit, REG_TEMP0, MP_F_CONST_NONE_OBJ); + ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); } else { emit_native_leave_exc_stack(emit, false); From 888ddb81ddfe9cd43991f8054967a0f0d5911cf1 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 24 Jan 2020 18:01:55 +1100 Subject: [PATCH 0911/1299] py/emitnative: Stop after finding an unwind target. The loop searches backwards for a target, but doesn't stop after finding the first result, meaning that it'll always end up at the outermost exception handler. --- py/emitnative.c | 1 + 1 file changed, 1 insertion(+) diff --git a/py/emitnative.c b/py/emitnative.c index 0affbeb0b2747..d0252560fef28 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -2774,6 +2774,7 @@ STATIC void emit_native_yield(emit_t *emit, int kind) { // Found active handler, get its PC ASM_MOV_REG_PCREL(emit->as, REG_RET, e->label); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_RET); + break; } } } From c3095b37e96aeb69564f53d30a12242ab42bbd02 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Fri, 24 Jan 2020 18:04:51 +1100 Subject: [PATCH 0912/1299] py/nativeglue: Fix typo about where the native fun table enum is. --- py/nativeglue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/nativeglue.c b/py/nativeglue.c index 9be7449d201a6..2e0ac56ca574b 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -253,7 +253,7 @@ STATIC double mp_obj_get_float_to_d(mp_obj_t o) { #endif -// these must correspond to the respective enum in runtime0.h +// these must correspond to the respective enum in nativeglue.h const mp_fun_table_t mp_fun_table = { mp_const_none, mp_const_false, From a542c6d7e0340e5ff5364426131bdbd69a64e746 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 29 Jan 2020 16:49:13 +1100 Subject: [PATCH 0913/1299] stm32/powerctrl: For F7, allow PLLM!=HSE when setting PLLSAI to 48MHz. PLLM is shared among all PLL blocks on F7 MCUs, and this calculation to configure PLLSAI to have 48MHz on the P output previously assumed that PLLM is equal to HSE (eg PLLM=25 for HSE=25MHz). This commit relaxes this assumption to allow other values of PLLM. --- ports/stm32/powerctrl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index dfd9e8262d940..1d1792c386ded 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -94,9 +94,11 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk if (need_pllsai) { // Configure PLLSAI at 48MHz for those peripherals that need this freq - const uint32_t pllsain = 192; + // (calculation assumes it can get an integral value of PLLSAIN) + const uint32_t pllm = (RCC->PLLCFGR >> RCC_PLLCFGR_PLLM_Pos) & 0x3f; const uint32_t pllsaip = 4; const uint32_t pllsaiq = 2; + const uint32_t pllsain = 48 * pllsaip * pllm / (HSE_VALUE / 1000000); RCC->PLLSAICFGR = pllsaiq << RCC_PLLSAICFGR_PLLSAIQ_Pos | (pllsaip / 2 - 1) << RCC_PLLSAICFGR_PLLSAIP_Pos | pllsain << RCC_PLLSAICFGR_PLLSAIN_Pos; From b72cb0ca1bb27396a5dcba9ce8a6f00dbd3d5f19 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 24 Jan 2020 11:37:53 -0600 Subject: [PATCH 0914/1299] py/mpthread.h: Use strong type for mp_thread_set_state() argument. This modifies the signature of mp_thread_set_state() to use mp_state_thread_t* instead of void*. This matches the return type of mp_thread_get_state(), which returns the same value. `struct _mp_state_thread_t;` had to be moved before `#include ` since the stm32 port uses it in its mpthreadport.h file. --- ports/cc3200/mpthreadport.c | 2 +- ports/esp32/mpthreadport.c | 2 +- ports/stm32/mpthreadport.h | 2 +- ports/unix/mpthreadport.c | 2 +- py/mpthread.h | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/cc3200/mpthreadport.c b/ports/cc3200/mpthreadport.c index 9dbc518e06dcc..f2fc76bdb019d 100644 --- a/ports/cc3200/mpthreadport.c +++ b/ports/cc3200/mpthreadport.c @@ -85,7 +85,7 @@ mp_state_thread_t *mp_thread_get_state(void) { return pvTaskGetThreadLocalStoragePointer(NULL, 0); } -void mp_thread_set_state(void *state) { +void mp_thread_set_state(mp_state_thread_t *state) { vTaskSetThreadLocalStoragePointer(NULL, 0, state); } diff --git a/ports/esp32/mpthreadport.c b/ports/esp32/mpthreadport.c index d7db0ff615226..febd01a6aae57 100644 --- a/ports/esp32/mpthreadport.c +++ b/ports/esp32/mpthreadport.c @@ -92,7 +92,7 @@ mp_state_thread_t *mp_thread_get_state(void) { return pvTaskGetThreadLocalStoragePointer(NULL, 1); } -void mp_thread_set_state(void *state) { +void mp_thread_set_state(mp_state_thread_t *state) { vTaskSetThreadLocalStoragePointer(NULL, 1, state); } diff --git a/ports/stm32/mpthreadport.h b/ports/stm32/mpthreadport.h index 8e2372dcb4350..e2b39979fb4c8 100644 --- a/ports/stm32/mpthreadport.h +++ b/ports/stm32/mpthreadport.h @@ -32,7 +32,7 @@ typedef pyb_mutex_t mp_thread_mutex_t; void mp_thread_init(void); void mp_thread_gc_others(void); -static inline void mp_thread_set_state(void *state) { +static inline void mp_thread_set_state(struct _mp_state_thread_t *state) { pyb_thread_set_local(state); } diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c index 4fe5fa9218811..b1915f2a6b3d8 100644 --- a/ports/unix/mpthreadport.c +++ b/ports/unix/mpthreadport.c @@ -158,7 +158,7 @@ mp_state_thread_t *mp_thread_get_state(void) { return (mp_state_thread_t*)pthread_getspecific(tls_key); } -void mp_thread_set_state(void *state) { +void mp_thread_set_state(mp_state_thread_t *state) { pthread_setspecific(tls_key, state); } diff --git a/py/mpthread.h b/py/mpthread.h index 602df830c49ab..f2ab081e70f67 100644 --- a/py/mpthread.h +++ b/py/mpthread.h @@ -30,16 +30,16 @@ #if MICROPY_PY_THREAD +struct _mp_state_thread_t; + #ifdef MICROPY_MPTHREADPORT_H #include MICROPY_MPTHREADPORT_H #else #include #endif -struct _mp_state_thread_t; - struct _mp_state_thread_t *mp_thread_get_state(void); -void mp_thread_set_state(void *state); +void mp_thread_set_state(struct _mp_state_thread_t *state); void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size); void mp_thread_start(void); void mp_thread_finish(void); From 30501d3f54fa642770faefa117b4c39d95aff549 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 28 Jan 2020 14:59:05 +1100 Subject: [PATCH 0915/1299] drivers, stm32: Support SPI/QSPI flash chips over 16MB. With a SPI flash that has more than 16MB, 32-bit addressing is required rather than the standard 24-bit. This commit adds support for 32-bit addressing so that the SPI flash commands (read/write/erase) are selected automatically depending on the size of the address being used at each operation. --- drivers/bus/qspi.h | 17 +++++++++++++++ drivers/bus/softqspi.c | 10 +++++---- drivers/memory/spiflash.c | 44 ++++++++++++++++++++++++--------------- ports/stm32/qspi.c | 24 ++++++++++++++++----- 4 files changed, 69 insertions(+), 26 deletions(-) diff --git a/drivers/bus/qspi.h b/drivers/bus/qspi.h index 31c9d14fca9e3..c82796fac5013 100644 --- a/drivers/bus/qspi.h +++ b/drivers/bus/qspi.h @@ -28,6 +28,8 @@ #include "py/mphal.h" +#define MP_SPI_ADDR_IS_32B(addr) (addr & 0xff000000) + enum { MP_QSPI_IOCTL_INIT, MP_QSPI_IOCTL_DEINIT, @@ -54,4 +56,19 @@ typedef struct _mp_soft_qspi_obj_t { extern const mp_qspi_proto_t mp_soft_qspi_proto; +static inline uint8_t mp_spi_set_addr_buff(uint8_t *buf, uint32_t addr) { + if (MP_SPI_ADDR_IS_32B(addr)) { + buf[0] = addr >> 24; + buf[1] = addr >> 16; + buf[2] = addr >> 8; + buf[3] = addr; + return 4; + } else { + buf[0] = addr >> 16; + buf[1] = addr >> 8; + buf[2] = addr; + return 3; + } +} + #endif // MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H diff --git a/drivers/bus/softqspi.c b/drivers/bus/softqspi.c index 10c5992466d82..71ab559768b1b 100644 --- a/drivers/bus/softqspi.c +++ b/drivers/bus/softqspi.c @@ -168,9 +168,10 @@ STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; - uint8_t cmd_buf[4] = {cmd, addr >> 16, addr >> 8, addr}; + uint8_t cmd_buf[5] = {cmd}; + uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr); CS_LOW(self); - mp_soft_qspi_transfer(self, 4, cmd_buf, NULL); + mp_soft_qspi_transfer(self, addr_len + 1, cmd_buf, NULL); mp_soft_qspi_transfer(self, len, src, NULL); CS_HIGH(self); } @@ -186,10 +187,11 @@ STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in; - uint8_t cmd_buf[7] = {cmd, addr >> 16, addr >> 8, addr}; + uint8_t cmd_buf[7] = {cmd}; + uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr); CS_LOW(self); mp_soft_qspi_transfer(self, 1, cmd_buf, NULL); - mp_soft_qspi_qwrite(self, 6, &cmd_buf[1]); // 3 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles) + mp_soft_qspi_qwrite(self, addr_len + 3, &cmd_buf[1]); // 3/4 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles) mp_soft_qspi_qread(self, len, dest); CS_HIGH(self); } diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c index 0eacc710e3475..e870d39f5f9cb 100644 --- a/drivers/memory/spiflash.c +++ b/drivers/memory/spiflash.c @@ -45,6 +45,12 @@ #define CMD_CHIP_ERASE (0xc7) #define CMD_C4READ (0xeb) +// 32 bit addressing commands +#define CMD_WRITE_32 (0x12) +#define CMD_READ_32 (0x13) +#define CMD_SEC_ERASE_32 (0x21) +#define CMD_C4READ_32 (0xec) + #define WAIT_SR_TIMEOUT (1000000) #define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer @@ -76,18 +82,26 @@ STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t } } -STATIC void mp_spiflash_write_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { +STATIC void mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) { const mp_spiflash_config_t *c = self->config; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { - uint8_t buf[4] = {cmd, addr >> 16, addr >> 8, addr}; + uint8_t buf[5] = {cmd, 0}; + uint8_t buff_len = 1 + mp_spi_set_addr_buff(&buf[1], addr); mp_hal_pin_write(c->bus.u_spi.cs, 0); - c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL); - if (len) { + c->bus.u_spi.proto->transfer(c->bus.u_spi.data, buff_len, buf, NULL); + if (len && (src != NULL)) { c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, src, NULL); + } else if (len && (dest != NULL)) { + c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest); } + mp_hal_pin_write(c->bus.u_spi.cs, 1); } else { - c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src); + if (dest != NULL) { + c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest); + } else { + c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src); + } } } @@ -107,25 +121,19 @@ STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t le STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { const mp_spiflash_config_t *c = self->config; + uint8_t cmd; if (c->bus_kind == MP_SPIFLASH_BUS_SPI) { - uint8_t buf[4] = {CMD_READ, addr >> 16, addr >> 8, addr}; - mp_hal_pin_write(c->bus.u_spi.cs, 0); - c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL); - c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest); - mp_hal_pin_write(c->bus.u_spi.cs, 1); + cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_READ_32 : CMD_READ; } else { - c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, CMD_C4READ, addr, len, dest); + cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_C4READ_32 : CMD_C4READ; } + mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest); } STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) { mp_spiflash_write_cmd_data(self, cmd, 0, 0); } -STATIC void mp_spiflash_write_cmd_addr(mp_spiflash_t *self, uint8_t cmd, uint32_t addr) { - mp_spiflash_write_cmd_addr_data(self, cmd, addr, 0, NULL); -} - STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) { uint8_t sr; do { @@ -210,7 +218,8 @@ STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) } // erase the sector - mp_spiflash_write_cmd_addr(self, CMD_SEC_ERASE, addr); + uint8_t cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_SEC_ERASE_32 : CMD_SEC_ERASE; + mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL); // wait WIP=0 return mp_spiflash_wait_wip0(self); @@ -227,7 +236,8 @@ STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len } // write the page - mp_spiflash_write_cmd_addr_data(self, CMD_WRITE, addr, len, src); + uint8_t cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_WRITE_32 : CMD_WRITE; + mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL); // wait WIP=0 return mp_spiflash_wait_wip0(self); diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 30ee2c9ea7aef..20cdafb00dc12 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -52,6 +52,14 @@ #define MICROPY_HW_QSPI_CS_HIGH_CYCLES 2 // nCS stays high for 2 cycles #endif +#if (MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 - 3 - 1) >= 24 +#define QSPI_CMD 0xec +#define QSPI_ADSIZE 3 +#else +#define QSPI_CMD 0xeb +#define QSPI_ADSIZE 2 +#endif + static inline void qspi_mpu_disable_all(void) { // Configure MPU to disable access to entire QSPI region, to prevent CPU // speculative execution from accessing this region and modifying QSPI registers. @@ -116,6 +124,7 @@ void qspi_memory_map(void) { // Enable memory-mapped mode QUADSPI->ABR = 0; // disable continuous read mode + QUADSPI->CCR = 0 << QUADSPI_CCR_DDRM_Pos // DDR mode disabled | 0 << QUADSPI_CCR_SIOO_Pos // send instruction every transaction @@ -124,10 +133,10 @@ void qspi_memory_map(void) { | 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles | 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte | 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines - | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size + | QSPI_ADSIZE << QUADSPI_CCR_ADSIZE_Pos | 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line - | 0xeb << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode + | QSPI_CMD << QUADSPI_CCR_INSTRUCTION_Pos ; qspi_mpu_enable_mapped(); @@ -203,6 +212,8 @@ STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) { (void)self_in; + uint8_t adsize = MP_SPI_ADDR_IS_32B(addr) ? 3 : 2; + QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag if (len == 0) { @@ -213,7 +224,7 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, | 0 << QUADSPI_CCR_DMODE_Pos // no data | 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles | 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte - | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size + | adsize << QUADSPI_CCR_ADSIZE_Pos // 32/24-bit address size | 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode @@ -230,7 +241,7 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, | 1 << QUADSPI_CCR_DMODE_Pos // data on 1 line | 0 << QUADSPI_CCR_DCYC_Pos // 0 dummy cycles | 0 << QUADSPI_CCR_ABMODE_Pos // no alternate byte - | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size + | adsize << QUADSPI_CCR_ADSIZE_Pos // 32/24-bit address size | 1 << QUADSPI_CCR_ADMODE_Pos // address on 1 line | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // write opcode @@ -285,6 +296,9 @@ STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) { STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) { (void)self_in; + + uint8_t adsize = MP_SPI_ADDR_IS_32B(addr) ? 3 : 2; + QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag QUADSPI->DLR = len - 1; // number of bytes to read @@ -297,7 +311,7 @@ STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, | 4 << QUADSPI_CCR_DCYC_Pos // 4 dummy cycles | 0 << QUADSPI_CCR_ABSIZE_Pos // 8-bit alternate byte | 3 << QUADSPI_CCR_ABMODE_Pos // alternate byte on 4 lines - | 2 << QUADSPI_CCR_ADSIZE_Pos // 24-bit address size + | adsize << QUADSPI_CCR_ADSIZE_Pos // 32 or 24-bit address size | 3 << QUADSPI_CCR_ADMODE_Pos // address on 4 lines | 1 << QUADSPI_CCR_IMODE_Pos // instruction on 1 line | cmd << QUADSPI_CCR_INSTRUCTION_Pos // quad read opcode From 7bb2bf965e529302aececb30d0b42014cac641fa Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jan 2020 14:39:46 +1100 Subject: [PATCH 0916/1299] stm32/Makefile: Allow a board's .mk file to add things to CFLAGS. --- ports/stm32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 6a6242df53305..96f10fe98a792 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -87,7 +87,7 @@ CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES)) CFLAGS += $(COPT) From 96a4435be1279dcb7804850311e551f2b06d86bd Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jan 2020 14:40:38 +1100 Subject: [PATCH 0917/1299] stm32/boards/STM32F769DISC: Add config to use external SPI as filesys. This board now has the following 3 build configurations: - mboot + external QSPI in XIP mode + internal filesystem - mboot + external QSPI with filesystem (the default) - no mboot + external QSPI with filesystem --- ports/stm32/boards/STM32F769DISC/board_init.c | 7 ++++-- .../boards/STM32F769DISC/mpconfigboard.h | 21 ++++++++++++++---- .../boards/STM32F769DISC/mpconfigboard.mk | 22 ++++++++++++------- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/ports/stm32/boards/STM32F769DISC/board_init.c b/ports/stm32/boards/STM32F769DISC/board_init.c index b75a00c970539..67fad407a0e28 100644 --- a/ports/stm32/boards/STM32F769DISC/board_init.c +++ b/ports/stm32/boards/STM32F769DISC/board_init.c @@ -1,16 +1,19 @@ -#include "drivers/memory/spiflash.h" +#include "storage.h" #include "qspi.h" // This configuration is needed for mboot to be able to write to the external QSPI flash +STATIC mp_spiflash_cache_t spi_bdev_cache; + const mp_spiflash_config_t spiflash_config = { .bus_kind = MP_SPIFLASH_BUS_QSPI, .bus.u_qspi.data = NULL, .bus.u_qspi.proto = &qspi_proto, .cache = NULL, + .cache = &spi_bdev_cache, }; -mp_spiflash_t spiflash_instance; +spi_bdev_t spi_bdev; // This init function is needed to memory map the QSPI flash early in the boot process diff --git a/ports/stm32/boards/STM32F769DISC/mpconfigboard.h b/ports/stm32/boards/STM32F769DISC/mpconfigboard.h index a34b58e1b2992..68e14761ecadc 100644 --- a/ports/stm32/boards/STM32F769DISC/mpconfigboard.h +++ b/ports/stm32/boards/STM32F769DISC/mpconfigboard.h @@ -26,7 +26,7 @@ void board_early_init(void); #define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_7 // 210-216 MHz needs 7 wait states -// 512MBit external QSPI flash, to be memory mapped +// 512MBit external QSPI flash, used for either the filesystem or XIP memory mapped #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (29) #define MICROPY_HW_QSPIFLASH_CS (pin_B6) #define MICROPY_HW_QSPIFLASH_SCK (pin_B2) @@ -35,6 +35,21 @@ void board_early_init(void); #define MICROPY_HW_QSPIFLASH_IO2 (pin_E2) #define MICROPY_HW_QSPIFLASH_IO3 (pin_D13) +// SPI flash, block device config (when used as the filesystem) +extern const struct _mp_spiflash_config_t spiflash_config; +extern struct _spi_bdev_t spi_bdev; +#if !USE_QSPI_XIP +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) +#define MICROPY_HW_BDEV_IOCTL(op, arg) ( \ + (op) == BDEV_IOCTL_NUM_BLOCKS ? (64 * 1024 * 1024 / FLASH_BLOCK_SIZE) : \ + (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \ + spi_bdev_ioctl(&spi_bdev, (op), (arg)) \ +) +#define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n)) +#define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n)) +#define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev) // for extended block protocol +#endif + // UART config #define MICROPY_HW_UART1_TX (pin_A9) #define MICROPY_HW_UART1_RX (pin_A10) @@ -199,11 +214,9 @@ void board_early_init(void); // Bootloader configuration // Give Mboot access to the external QSPI flash -extern const struct _mp_spiflash_config_t spiflash_config; -extern struct _mp_spiflash_t spiflash_instance; #define MBOOT_SPIFLASH_ADDR (0x90000000) #define MBOOT_SPIFLASH_BYTE_SIZE (512 * 128 * 1024) #define MBOOT_SPIFLASH_LAYOUT "/0x90000000/512*128Kg" #define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (128 / 4) // 128k page, 4k erase block #define MBOOT_SPIFLASH_CONFIG (&spiflash_config) -#define MBOOT_SPIFLASH_SPIFLASH (&spiflash_instance) +#define MBOOT_SPIFLASH_SPIFLASH (&spi_bdev.spiflash) diff --git a/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk b/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk index 04f208c5b7f78..81add8c88e772 100644 --- a/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk +++ b/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk @@ -1,9 +1,11 @@ # By default this board is configured to use mboot which must be deployed first USE_MBOOT ?= 1 -# By default this board puts some code into external QSPI flash set in XIP mode +# By default the filesystem is in external QSPI flash. But by setting the +# following option this board puts some code into external flash set in XIP mode. # USE_MBOOT must be enabled; see f769_qspi.ld for code that goes in QSPI flash -USE_QSPI ?= 1 +USE_QSPI_XIP ?= 0 +CFLAGS += -DUSE_QSPI_XIP=$(USE_QSPI_XIP) # MCU settings MCU_SERIES = f7 @@ -12,9 +14,11 @@ MICROPY_FLOAT_IMPL = double AF_FILE = boards/stm32f767_af.csv ifeq ($(USE_MBOOT),1) -ifeq ($(USE_QSPI),1) +ifeq ($(USE_QSPI_XIP),1) -# When using Mboot and QSPI the text is split between internal and external flash +# When using Mboot and QSPI-XIP the text is split between internal and external +# QSPI flash, and the filesystem is in internal flash between the bootloader and +# the main program text. LD_FILES = boards/STM32F769DISC/f769_qspi.ld TEXT0_ADDR = 0x08020000 TEXT1_ADDR = 0x90000000 @@ -23,17 +27,19 @@ TEXT1_SECTIONS = .text_qspi else -# When using Mboot but not QSPI all the text goes together after the filesystem +# When using Mboot but not QSPI-XIP all the text goes together after the bootloader +# (at same location as when QSPI-XIP is enabled so the same Mboot can be used for +# either configuration) and the filesystem is in external flash. LD_FILES = boards/stm32f769.ld boards/common_blifs.ld TEXT0_ADDR = 0x08020000 endif else -# When not using Mboot the ISR text goes first, then the rest after the filesystem -LD_FILES = boards/stm32f769.ld boards/common_ifs.ld +# When not using Mboot (and so no ability to load text into QSPI) all the text goes +# together at the start of internal flash, and the filesystem is in external flash. +LD_FILES = boards/stm32f769.ld boards/common_basic.ld TEXT0_ADDR = 0x08000000 -TEXT1_ADDR = 0x08020000 endif From c3450effd4c3a402eeccf44a84a05ef4b36d69a0 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jan 2020 00:15:26 +1100 Subject: [PATCH 0918/1299] py/objtype: Make mp_obj_type_t.flags constants public, moved to obj.h. --- py/obj.h | 4 ++++ py/objtype.c | 21 +++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/py/obj.h b/py/obj.h index b052b9fc8b5c2..2bc72b58679d3 100644 --- a/py/obj.h +++ b/py/obj.h @@ -444,6 +444,10 @@ typedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *); // this arg to mp_map_lookup(). typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); +// Flags for type behaviour (mp_obj_type_t.flags) +#define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) +#define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) + typedef enum { PRINT_STR = 0, PRINT_REPR = 1, diff --git a/py/objtype.c b/py/objtype.c index 2ea3f1c18728c..c574dcdfe2c6c 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -44,9 +44,6 @@ #define ENABLE_SPECIAL_ACCESSORS \ (MICROPY_PY_DESCRIPTORS || MICROPY_PY_DELATTR_SETATTR || MICROPY_PY_BUILTINS_PROPERTY) -#define TYPE_FLAG_IS_SUBCLASSED (0x0001) -#define TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) - STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); /******************************************************************************/ @@ -615,7 +612,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) { - if (!(self->base.type->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { + if (!(self->base.type->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { // Class doesn't have any special accessors to check so return straightaway return; } @@ -680,7 +677,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); - if (!(self->base.type->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { + if (!(self->base.type->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { // Class doesn't have any special accessors so skip their checks goto skip_special_accessors; } @@ -1061,13 +1058,13 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } else { #if ENABLE_SPECIAL_ACCESSORS // Check if we add any special accessor methods with this store - if (!(self->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { + if (!(self->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { if (check_for_special_accessors(MP_OBJ_NEW_QSTR(attr), dest[1])) { - if (self->flags & TYPE_FLAG_IS_SUBCLASSED) { + if (self->flags & MP_TYPE_FLAG_IS_SUBCLASSED) { // This class is already subclassed so can't have special accessors added mp_raise_msg(&mp_type_AttributeError, "can't add special method to already-subclassed class"); } - self->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS; + self->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; } } #endif @@ -1123,8 +1120,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } #if ENABLE_SPECIAL_ACCESSORS if (mp_obj_is_instance_type(t)) { - t->flags |= TYPE_FLAG_IS_SUBCLASSED; - base_flags |= t->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS; + t->flags |= MP_TYPE_FLAG_IS_SUBCLASSED; + base_flags |= t->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; } #endif } @@ -1166,12 +1163,12 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) #if ENABLE_SPECIAL_ACCESSORS // Check if the class has any special accessor methods - if (!(o->flags & TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { + if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { for (size_t i = 0; i < o->locals_dict->map.alloc; i++) { if (mp_map_slot_is_filled(&o->locals_dict->map, i)) { const mp_map_elem_t *elem = &o->locals_dict->map.table[i]; if (check_for_special_accessors(elem->key, elem->value)) { - o->flags |= TYPE_FLAG_HAS_SPECIAL_ACCESSORS; + o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; break; } } From 3aab54bf434e7f025a91ea05052f1bac439fad8c Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Tue, 31 Dec 2019 15:19:12 -0700 Subject: [PATCH 0919/1299] py: Support non-boolean results for equality and inequality tests. This commit implements a more complete replication of CPython's behaviour for equality and inequality testing of objects. This addresses the issues discussed in #5382 and a few other inconsistencies. Improvements over the old code include: - Support for returning non-boolean results from comparisons (as used by numpy and others). - Support for non-reflexive equality tests. - Preferential use of __ne__ methods and MP_BINARY_OP_NOT_EQUAL binary operators for inequality tests, when available. - Fallback to op2 == op1 or op2 != op1 when op1 does not implement the (in)equality operators. The scheme here makes use of a new flag, MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST, in the flags word of mp_obj_type_t to indicate if various shortcuts can or cannot be used when performing equality and inequality tests. Currently four built-in classes have the flag set: float and complex are non-reflexive (since nan != nan) while bytearray and frozenszet instances can equal other builtin class instances (bytes and set respectively). The flag is also set for any new class defined by the user. This commit also includes a more comprehensive set of tests for the behaviour of (in)equality operators implemented in special methods. --- py/obj.c | 112 ++++++++++++++++----------- py/obj.h | 7 ++ py/objarray.c | 1 + py/objcomplex.c | 1 + py/objfloat.c | 1 + py/objset.c | 1 + py/objtype.c | 4 +- py/runtime.c | 15 +--- tests/basics/special_comparisons.py | 33 ++++++++ tests/basics/special_comparisons2.py | 31 ++++++++ 10 files changed, 146 insertions(+), 60 deletions(-) create mode 100644 tests/basics/special_comparisons.py create mode 100644 tests/basics/special_comparisons2.py diff --git a/py/obj.c b/py/obj.c index 55754f9be27e7..6aa0abf0d336b 100644 --- a/py/obj.c +++ b/py/obj.c @@ -189,7 +189,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) { return mp_obj_instance_is_callable(o_in); } -// This function implements the '==' operator (and so the inverse of '!='). +// This function implements the '==' and '!=' operators. // // From the Python language reference: // (https://docs.python.org/3/reference/expressions.html#not-in) @@ -202,67 +202,89 @@ bool mp_obj_is_callable(mp_obj_t o_in) { // Furthermore, from the v3.4.2 code for object.c: "Practical amendments: If rich // comparison returns NotImplemented, == and != are decided by comparing the object // pointer." -bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { - // Float (and complex) NaN is never equal to anything, not even itself, - // so we must have a special check here to cover those cases. - if (o1 == o2 - #if MICROPY_PY_BUILTINS_FLOAT - && !mp_obj_is_float(o1) - #endif - #if MICROPY_PY_BUILTINS_COMPLEX - && !mp_obj_is_type(o1, &mp_type_complex) - #endif - ) { - return true; - } - if (o1 == mp_const_none || o2 == mp_const_none) { - return false; - } +mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2) { + mp_obj_t local_true = (op == MP_BINARY_OP_NOT_EQUAL) ? mp_const_false : mp_const_true; + mp_obj_t local_false = (op == MP_BINARY_OP_NOT_EQUAL) ? mp_const_true : mp_const_false; + int pass_number = 0; - // fast path for small ints - if (mp_obj_is_small_int(o1)) { - if (mp_obj_is_small_int(o2)) { - // both SMALL_INT, and not equal if we get here - return false; - } else { - mp_obj_t temp = o2; o2 = o1; o1 = temp; - // o2 is now the SMALL_INT, o1 is not - // fall through to generic op - } + // Shortcut for very common cases + if (o1 == o2 && + (mp_obj_is_small_int(o1) || !(mp_obj_get_type(o1)->flags & MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST))) { + return local_true; } // fast path for strings if (mp_obj_is_str(o1)) { if (mp_obj_is_str(o2)) { // both strings, use special function - return mp_obj_str_equal(o1, o2); + return mp_obj_str_equal(o1, o2) ? local_true : local_false; + #if MICROPY_PY_STR_BYTES_CMP_WARN + } else if (mp_obj_is_type(o2, &mp_type_bytes)) { + str_bytes_cmp: + mp_warning(MP_WARN_CAT(BytesWarning), "Comparison between bytes and str"); + return local_false; + #endif } else { - // a string is never equal to anything else - goto str_cmp_err; + goto skip_one_pass; } - } else if (mp_obj_is_str(o2)) { + #if MICROPY_PY_STR_BYTES_CMP_WARN + } else if (mp_obj_is_str(o2) && mp_obj_is_type(o1, &mp_type_bytes)) { // o1 is not a string (else caught above), so the objects are not equal - str_cmp_err: - #if MICROPY_PY_STR_BYTES_CMP_WARN - if (mp_obj_is_type(o1, &mp_type_bytes) || mp_obj_is_type(o2, &mp_type_bytes)) { - mp_warning(MP_WARN_CAT(BytesWarning), "Comparison between bytes and str"); + goto str_bytes_cmp; + #endif + } + + // fast path for small ints + if (mp_obj_is_small_int(o1)) { + if (mp_obj_is_small_int(o2)) { + // both SMALL_INT, and not equal if we get here + return local_false; + } else { + goto skip_one_pass; } - #endif - return false; } // generic type, call binary_op(MP_BINARY_OP_EQUAL) - const mp_obj_type_t *type = mp_obj_get_type(o1); - if (type->binary_op != NULL) { - mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); - if (r != MP_OBJ_NULL) { - return r == mp_const_true ? true : false; + while (pass_number < 2) { + const mp_obj_type_t *type = mp_obj_get_type(o1); + // If a full equality test is not needed and the other object is a different + // type then we don't need to bother trying the comparison. + if (type->binary_op != NULL && + ((type->flags & MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST) || mp_obj_get_type(o2) == type)) { + // CPython is asymmetric: it will try __eq__ if there's no __ne__ but not the + // other way around. If the class doesn't need a full test we can skip __ne__. + if (op == MP_BINARY_OP_NOT_EQUAL && (type->flags & MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST)) { + mp_obj_t r = type->binary_op(MP_BINARY_OP_NOT_EQUAL, o1, o2); + if (r != MP_OBJ_NULL) { + return r; + } + } + + // Try calling __eq__. + mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); + if (r != MP_OBJ_NULL) { + if (op == MP_BINARY_OP_EQUAL) { + return r; + } else { + return mp_obj_is_true(r) ? local_true : local_false; + } + } } + + skip_one_pass: + // Try the other way around if none of the above worked + ++pass_number; + mp_obj_t temp = o1; + o1 = o2; + o2 = temp; } - // equality not implemented, and objects are not the same object, so - // they are defined as not equal - return false; + // equality not implemented, so fall back to pointer conparison + return (o1 == o2) ? local_true : local_false; +} + +bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { + return mp_obj_is_true(mp_obj_equal_not_equal(MP_BINARY_OP_EQUAL, o1, o2)); } mp_int_t mp_obj_get_int(mp_const_obj_t arg) { diff --git a/py/obj.h b/py/obj.h index 2bc72b58679d3..2e91b6b150c16 100644 --- a/py/obj.h +++ b/py/obj.h @@ -445,8 +445,14 @@ typedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *); typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // Flags for type behaviour (mp_obj_type_t.flags) +// If MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST is clear then all the following hold: +// (a) the type only implements the __eq__ operator and not the __ne__ operator; +// (b) __eq__ returns a boolean result (False or True); +// (c) __eq__ is reflexive (A==A is True); +// (d) the type can't be equal to an instance of any different class that also clears this flag. #define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) #define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) +#define MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST (0x0004) typedef enum { PRINT_STR = 0, @@ -729,6 +735,7 @@ void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc); bool mp_obj_is_true(mp_obj_t arg); bool mp_obj_is_callable(mp_obj_t o_in); +mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2); bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); static inline bool mp_obj_is_integer(mp_const_obj_t o) { return mp_obj_is_int(o) || mp_obj_is_bool(o); } // returns true if o is bool, small int or long int diff --git a/py/objarray.c b/py/objarray.c index c19617d4e1dd6..51f924ba4e648 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -558,6 +558,7 @@ const mp_obj_type_t mp_type_array = { const mp_obj_type_t mp_type_bytearray = { { &mp_type_type }, .name = MP_QSTR_bytearray, + .flags = MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST, .print = array_print, .make_new = bytearray_make_new, .getiter = array_iterator_new, diff --git a/py/objcomplex.c b/py/objcomplex.c index bf6fb51dc558e..0c87f544fb722 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -148,6 +148,7 @@ STATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { const mp_obj_type_t mp_type_complex = { { &mp_type_type }, .name = MP_QSTR_complex, + .flags = MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST, .print = complex_print, .make_new = complex_make_new, .unary_op = complex_unary_op, diff --git a/py/objfloat.c b/py/objfloat.c index 3da549bb25a5c..6181d5f578648 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -186,6 +186,7 @@ STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs const mp_obj_type_t mp_type_float = { { &mp_type_type }, .name = MP_QSTR_float, + .flags = MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST, .print = float_print, .make_new = float_make_new, .unary_op = float_unary_op, diff --git a/py/objset.c b/py/objset.c index 6f5bcc032a9a5..a18b7e051ef32 100644 --- a/py/objset.c +++ b/py/objset.c @@ -564,6 +564,7 @@ STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); const mp_obj_type_t mp_type_frozenset = { { &mp_type_type }, .name = MP_QSTR_frozenset, + .flags = MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST, .print = set_print, .make_new = set_make_new, .unary_op = set_unary_op, diff --git a/py/objtype.c b/py/objtype.c index c574dcdfe2c6c..ae0fe6caef03e 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -467,7 +467,7 @@ const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = { [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__, [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__, [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__, - // MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result + [MP_BINARY_OP_NOT_EQUAL] = MP_QSTR___ne__, [MP_BINARY_OP_CONTAINS] = MP_QSTR___contains__, // If an inplace method is not found a normal method will be used as a fallback @@ -1100,7 +1100,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // TODO might need to make a copy of locals_dict; at least that's how CPython does it // Basic validation of base classes - uint16_t base_flags = 0; + uint16_t base_flags = MP_TYPE_FLAG_NEEDS_FULL_EQ_TEST; size_t bases_len; mp_obj_t *bases_items; mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items); diff --git a/py/runtime.c b/py/runtime.c index db044cf7c4c15..4a718c1e23327 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -323,19 +323,8 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { // deal with == and != for all types if (op == MP_BINARY_OP_EQUAL || op == MP_BINARY_OP_NOT_EQUAL) { - if (mp_obj_equal(lhs, rhs)) { - if (op == MP_BINARY_OP_EQUAL) { - return mp_const_true; - } else { - return mp_const_false; - } - } else { - if (op == MP_BINARY_OP_EQUAL) { - return mp_const_false; - } else { - return mp_const_true; - } - } + // mp_obj_equal_not_equal supports a bunch of shortcuts + return mp_obj_equal_not_equal(op, lhs, rhs); } // deal with exception_match for all types diff --git a/tests/basics/special_comparisons.py b/tests/basics/special_comparisons.py new file mode 100644 index 0000000000000..2ebd7e224efda --- /dev/null +++ b/tests/basics/special_comparisons.py @@ -0,0 +1,33 @@ +class A: + def __eq__(self, other): + print("A __eq__ called") + return True + +class B: + def __ne__(self, other): + print("B __ne__ called") + return True + +class C: + def __eq__(self, other): + print("C __eq__ called") + return False + +class D: + def __ne__(self, other): + print("D __ne__ called") + return False + +a = A() +b = B() +c = C() +d = D() + +def test(s): + print(s) + print(eval(s)) + +for x in 'abcd': + for y in 'abcd': + test('{} == {}'.format(x,y)) + test('{} != {}'.format(x,y)) diff --git a/tests/basics/special_comparisons2.py b/tests/basics/special_comparisons2.py new file mode 100644 index 0000000000000..c29dc72ce60c0 --- /dev/null +++ b/tests/basics/special_comparisons2.py @@ -0,0 +1,31 @@ +class E: + def __repr__(self): + return "E" + + def __eq__(self, other): + print('E eq', other) + return 123 + +class F: + def __repr__(self): + return "F" + + def __ne__(self, other): + print('F ne', other) + return -456 + +print(E() != F()) +print(F() != E()) + +tests = (None, 0, 1, 'a') + +for val in tests: + print('==== testing', val) + print(E() == val) + print(val == E()) + print(E() != val) + print(val != E()) + print(F() == val) + print(val == F()) + print(F() != val) + print(val != F()) From c96a2f636b48b065e8404af6d67fbae5986fd34a Mon Sep 17 00:00:00 2001 From: Nicko van Someren Date: Tue, 14 Jan 2020 21:40:08 -0700 Subject: [PATCH 0920/1299] tests/basics: Expand test cases for equality of subclasses. --- tests/basics/subclass_native2_tuple.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/basics/subclass_native2_tuple.py b/tests/basics/subclass_native2_tuple.py index 9eb69e1575e25..a02d3a66dcb2c 100644 --- a/tests/basics/subclass_native2_tuple.py +++ b/tests/basics/subclass_native2_tuple.py @@ -19,3 +19,11 @@ class Ctuple2(tuple, Base1): print(len(a)) a = Ctuple2([1, 2, 3]) print(len(a)) + +a = tuple([1,2,3]) +b = Ctuple1([1,2,3]) +c = Ctuple2([1,2,3]) + +print(a == b) +print(b == c) +print(c == a) From 29b84ea79856e8ba512ef7ea70b265e9d86e45b6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jan 2020 16:29:45 +1100 Subject: [PATCH 0921/1299] stm32/powerctrl: Disable HSI if not needed to save a bit of power. --- ports/stm32/powerctrl.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 1d1792c386ded..d1ac85f0e8055 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -44,6 +44,13 @@ extern uint32_t _estack[]; #define BL_STATE ((uint32_t*)&_estack) +static inline void powerctrl_disable_hsi_if_unused(void) { + #if !MICROPY_HW_CLK_USE_HSI && (defined(STM32F4) || defined(STM32F7) || defined(STM32H7)) + // Disable HSI if it's not used to save a little bit of power + __HAL_RCC_HSI_DISABLE(); + #endif +} + NORETURN void powerctrl_mcu_reset(void) { BL_STATE[1] = 1; // invalidate bootloader address #if __DCACHE_PRESENT == 1 @@ -155,6 +162,8 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk return -MP_EIO; } + powerctrl_disable_hsi_if_unused(); + return 0; } @@ -390,6 +399,8 @@ void powerctrl_enter_stop_mode(void) { } #endif + powerctrl_disable_hsi_if_unused(); + #if defined(STM32F7) if (RCC->DCKCFGR2 & RCC_DCKCFGR2_CK48MSEL) { // Enable PLLSAI if it is selected as 48MHz source From 68db7e01d842b0b9b828be6e001e83f78de7a226 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jan 2020 16:30:03 +1100 Subject: [PATCH 0922/1299] stm32/powerctrl: Enable overdrive on F7 when waking from stop mode. Because if the SYSCLK is set to 180MHz or higher it will require this to be on already. --- ports/stm32/powerctrl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index d1ac85f0e8055..4c40cffb60c27 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -381,6 +381,11 @@ void powerctrl_enter_stop_mode(void) { } #endif + #if defined(STM32F7) + // Enable overdrive to reach 216MHz (if needed) + HAL_PWREx_EnableOverDrive(); + #endif + // enable PLL __HAL_RCC_PLL_ENABLE(); while (!__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) { From 31ba06ce845938e4fff9a34163311a07d0e22cab Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 30 Jan 2020 16:31:11 +1100 Subject: [PATCH 0923/1299] stm32/boards/stm32f746_af.csv: Add ADC alt functions to correct pins. --- ports/stm32/boards/stm32f746_af.csv | 340 ++++++++++++++-------------- 1 file changed, 170 insertions(+), 170 deletions(-) diff --git a/ports/stm32/boards/stm32f746_af.csv b/ports/stm32/boards/stm32f746_af.csv index 8069edc7b9732..d9e42008d616f 100644 --- a/ports/stm32/boards/stm32f746_af.csv +++ b/ports/stm32/boards/stm32f746_af.csv @@ -1,170 +1,170 @@ -Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15 -,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4/5/6,SPI3/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI2/USART6/UART4/5/7/8/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI/LCD,SAI2/QUADSPI/OTG2_HS/OTG1_FS,ETH/OTG1_FS,FMC/SDMMC1/OTG2_FS,DCMI,LCD,SYS -PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT -PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT -PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,,,LCD_R1,EVENTOUT -PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT -PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT -PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT -PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCLK,LCD_G2,EVENTOUT -PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT -PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,LCD_R6,EVENTOUT -PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT -PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT -PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT -PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT -PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT -PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT -PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT -PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT -PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT -PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,,,,,,EVENTOUT -PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT -PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,,,,,,EVENTOUT -PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,,EVENTOUT -PortB,PB6,,,TIM4_CH1,HDMI_CEC,I2C1_SCL,,,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,,FMC_SDNE1,DCMI_D5,,EVENTOUT -PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT -PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT -PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT -PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT -PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT -PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT -PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT -PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT -PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT -PortC,PC0,,,,,,,,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT -PortC,PC1,TRACED0,,,,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,,ETH_MDC,,,,EVENTOUT -PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT -PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT -PortC,PC4,,,,,,I2S1_MCK,,,SPDIFRX_IN2,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT -PortC,PC5,,,,,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT -PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT -PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT -PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDMMC1_D0,DCMI_D2,,EVENTOUT -PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDMMC1_D1,DCMI_D3,,EVENTOUT -PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT -PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,DCMI_D4,,EVENTOUT -PortC,PC12,TRACED3,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9,,EVENTOUT -PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT -PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT -PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT -PortD,PD0,,,,,,,,,,CAN1_RX,,,FMC_D2,,,EVENTOUT -PortD,PD1,,,,,,,,,,CAN1_TX,,,FMC_D3,,,EVENTOUT -PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT -PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT -PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT -PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT -PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT -PortD,PD7,,,,,,,,USART2_CK,SPDIFRX_IN0,,,,FMC_NE1,,,EVENTOUT -PortD,PD8,,,,,,,,USART3_TX,SPDIFRX_IN1,,,,FMC_D13,,,EVENTOUT -PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT -PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT -PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT -PortD,PD12,,,TIM4_CH1,LPTIM1_IN1,I2C4_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,,,EVENTOUT -PortD,PD13,,,TIM4_CH2,LPTIM1_OUT,I2C4_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT -PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,,FMC_D0,,,EVENTOUT -PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,,FMC_D1,,,EVENTOUT -PortE,PE0,,,TIM4_ETR,LPTIM1_ETR,,,,,UART8_RX,,SAI2_MCK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT -PortE,PE1,,,,LPTIM1_IN2,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT -PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT -PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT -PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT -PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT -PortE,PE6,TRACED3,TIM1_BKIN2,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCK_B,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT -PortE,PE7,,TIM1_ETR,,,,,,,UART7_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT -PortE,PE8,,TIM1_CH1N,,,,,,,UART7_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT -PortE,PE9,,TIM1_CH1,,,,,,,UART7_RTS,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT -PortE,PE10,,TIM1_CH2N,,,,,,,UART7_CTS,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT -PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8,,LCD_G3,EVENTOUT -PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9,,LCD_B4,EVENTOUT -PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10,,LCD_DE,EVENTOUT -PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,FMC_D11,,LCD_CLK,EVENTOUT -PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,LCD_R7,EVENTOUT -PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT -PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT -PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT -PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT -PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT -PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT -PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT -PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT -PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,UART7_RTS,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT -PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,UART7_CTS,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT -PortF,PF10,,,,,,,,,,,,,,DCMI_D11,LCD_DE,EVENTOUT -PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT -PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT -PortF,PF13,,,,,I2C4_SMBA,,,,,,,,FMC_A7,,,EVENTOUT -PortF,PF14,,,,,I2C4_SCL,,,,,,,,FMC_A8,,,EVENTOUT -PortF,PF15,,,,,I2C4_SDA,,,,,,,,FMC_A9,,,EVENTOUT -PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT -PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT -PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT -PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT -PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT -PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT -PortG,PG6,,,,,,,,,,,,,,DCMI_D12,LCD_R7,EVENTOUT -PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT -PortG,PG8,,,,,,SPI6_NSS,,SPDIFRX_IN2,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT -PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT -PortG,PG10,,,,,,,,,,LCD_G3,SAI2_SD_B,,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT -PortG,PG11,,,,,,,,SPDIFRX_IN0,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT -PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,,FMC_NE4,,LCD_B1,EVENTOUT -PortG,PG13,TRACED0,,,LPTIM1_OUT,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT -PortG,PG14,TRACED1,,,LPTIM1_ETR,,SPI6_MOSI,,,USART6_TX,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT -PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT -PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT -PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT -PortH,PH2,,,,LPTIM1_IN2,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT -PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT -PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT -PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT -PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8,,EVENTOUT -PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,EVENTOUT -PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT -PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT -PortH,PH10,,,TIM5_CH1,,I2C4_SMBA,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT -PortH,PH11,,,TIM5_CH2,,I2C4_SCL,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT -PortH,PH12,,,TIM5_CH3,,I2C4_SDA,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT -PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT -PortH,PH14,,,,TIM8_CH2N,,,,,,,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT -PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT -PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT -PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT -PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT -PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT -PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT -PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT -PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT -PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT -PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT -PortI,PI9,,,,,,,,,,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT -PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT -PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT -PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT -PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT -PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT -PortI,PI15,,,,,,,,,,,,,,,LCD_R0,EVENTOUT -PortJ,PJ0,,,,,,,,,,,,,,,LCD_R1,EVENTOUT -PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT -PortJ,PJ2,,,,,,,,,,,,,,,LCD_R3,EVENTOUT -PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT -PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT -PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT -PortJ,PJ6,,,,,,,,,,,,,,,LCD_R7,EVENTOUT -PortJ,PJ7,,,,,,,,,,,,,,,LCD_G0,EVENTOUT -PortJ,PJ8,,,,,,,,,,,,,,,LCD_G1,EVENTOUT -PortJ,PJ9,,,,,,,,,,,,,,,LCD_G2,EVENTOUT -PortJ,PJ10,,,,,,,,,,,,,,,LCD_G3,EVENTOUT -PortJ,PJ11,,,,,,,,,,,,,,,LCD_G4,EVENTOUT -PortJ,PJ12,,,,,,,,,,,,,,,LCD_B0,EVENTOUT -PortJ,PJ13,,,,,,,,,,,,,,,LCD_B1,EVENTOUT -PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT -PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT -PortK,PK0,,,,,,,,,,,,,,,LCD_G5,EVENTOUT -PortK,PK1,,,,,,,,,,,,,,,LCD_G6,EVENTOUT -PortK,PK2,,,,,,,,,,,,,,,LCD_G7,EVENTOUT -PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT -PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT -PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT -PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT -PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, +,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4/5/6,SPI3/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI2/USART6/UART4/5/7/8/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI/LCD,SAI2/QUADSPI/OTG2_HS/OTG1_FS,ETH/OTG1_FS,FMC/SDMMC1/OTG2_FS,DCMI,LCD,SYS,ADC +PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0 +PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT,ADC123_IN1 +PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,,,LCD_R1,EVENTOUT,ADC123_IN2 +PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT,ADC123_IN3 +PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT,ADC12_IN4 +PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT,ADC12_IN5 +PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCLK,LCD_G2,EVENTOUT,ADC12_IN6 +PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT,ADC12_IN7 +PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,LCD_R6,EVENTOUT, +PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT, +PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT, +PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT, +PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT, +PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT, +PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT, +PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT,ADC12_IN8 +PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT,ADC12_IN9 +PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,,,,,,EVENTOUT, +PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT, +PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,,,,,,EVENTOUT, +PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,,EVENTOUT, +PortB,PB6,,,TIM4_CH1,HDMI_CEC,I2C1_SCL,,,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,,FMC_SDNE1,DCMI_D5,,EVENTOUT, +PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT, +PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT, +PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT, +PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT, +PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT, +PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT, +PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT, +PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT, +PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT, +PortC,PC0,,,,,,,,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT,ADC123_IN10 +PortC,PC1,TRACED0,,,,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,,ETH_MDC,,,,EVENTOUT,ADC123_IN11 +PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC123_IN12 +PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13 +PortC,PC4,,,,,,I2S1_MCK,,,SPDIFRX_IN2,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT,ADC12_IN14 +PortC,PC5,,,,,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT,ADC12_IN15 +PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT, +PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT, +PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDMMC1_D0,DCMI_D2,,EVENTOUT, +PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDMMC1_D1,DCMI_D3,,EVENTOUT, +PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT, +PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,DCMI_D4,,EVENTOUT, +PortC,PC12,TRACED3,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9,,EVENTOUT, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, +PortD,PD0,,,,,,,,,,CAN1_RX,,,FMC_D2,,,EVENTOUT, +PortD,PD1,,,,,,,,,,CAN1_TX,,,FMC_D3,,,EVENTOUT, +PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT, +PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT, +PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT, +PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT, +PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT, +PortD,PD7,,,,,,,,USART2_CK,SPDIFRX_IN0,,,,FMC_NE1,,,EVENTOUT, +PortD,PD8,,,,,,,,USART3_TX,SPDIFRX_IN1,,,,FMC_D13,,,EVENTOUT, +PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT, +PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT, +PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT, +PortD,PD12,,,TIM4_CH1,LPTIM1_IN1,I2C4_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,,,EVENTOUT, +PortD,PD13,,,TIM4_CH2,LPTIM1_OUT,I2C4_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT, +PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,,FMC_D0,,,EVENTOUT, +PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,,FMC_D1,,,EVENTOUT, +PortE,PE0,,,TIM4_ETR,LPTIM1_ETR,,,,,UART8_RX,,SAI2_MCK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT, +PortE,PE1,,,,LPTIM1_IN2,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT, +PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT, +PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT, +PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT, +PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT, +PortE,PE6,TRACED3,TIM1_BKIN2,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCK_B,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT, +PortE,PE7,,TIM1_ETR,,,,,,,UART7_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT, +PortE,PE8,,TIM1_CH1N,,,,,,,UART7_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT, +PortE,PE9,,TIM1_CH1,,,,,,,UART7_RTS,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT, +PortE,PE10,,TIM1_CH2N,,,,,,,UART7_CTS,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT, +PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8,,LCD_G3,EVENTOUT, +PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9,,LCD_B4,EVENTOUT, +PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10,,LCD_DE,EVENTOUT, +PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,FMC_D11,,LCD_CLK,EVENTOUT, +PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,LCD_R7,EVENTOUT, +PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT, +PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT, +PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT, +PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN9 +PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN14 +PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN15 +PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC3_IN4 +PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT,ADC3_IN5 +PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,UART7_RTS,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT,ADC3_IN6 +PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,UART7_CTS,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT,ADC3_IN7 +PortF,PF10,,,,,,,,,,,,,,DCMI_D11,LCD_DE,EVENTOUT,ADC3_IN8 +PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT, +PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT, +PortF,PF13,,,,,I2C4_SMBA,,,,,,,,FMC_A7,,,EVENTOUT, +PortF,PF14,,,,,I2C4_SCL,,,,,,,,FMC_A8,,,EVENTOUT, +PortF,PF15,,,,,I2C4_SDA,,,,,,,,FMC_A9,,,EVENTOUT, +PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT, +PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT, +PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT, +PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT, +PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT, +PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT, +PortG,PG6,,,,,,,,,,,,,,DCMI_D12,LCD_R7,EVENTOUT, +PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT, +PortG,PG8,,,,,,SPI6_NSS,,SPDIFRX_IN2,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT, +PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT, +PortG,PG10,,,,,,,,,,LCD_G3,SAI2_SD_B,,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT, +PortG,PG11,,,,,,,,SPDIFRX_IN0,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT, +PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,,FMC_NE4,,LCD_B1,EVENTOUT, +PortG,PG13,TRACED0,,,LPTIM1_OUT,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT, +PortG,PG14,TRACED1,,,LPTIM1_ETR,,SPI6_MOSI,,,USART6_TX,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT, +PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT, +PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH2,,,,LPTIM1_IN2,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT, +PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT, +PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT, +PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT, +PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8,,EVENTOUT, +PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,EVENTOUT, +PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT, +PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT, +PortH,PH10,,,TIM5_CH1,,I2C4_SMBA,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT, +PortH,PH11,,,TIM5_CH2,,I2C4_SCL,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT, +PortH,PH12,,,TIM5_CH3,,I2C4_SDA,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT, +PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT, +PortH,PH14,,,,TIM8_CH2N,,,,,,,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT, +PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT, +PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT, +PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT, +PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT, +PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT, +PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT, +PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT, +PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT, +PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT, +PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT, +PortI,PI9,,,,,,,,,,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT, +PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT, +PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT, +PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT, +PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT, +PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT, +PortI,PI15,,,,,,,,,,,,,,,LCD_R0,EVENTOUT, +PortJ,PJ0,,,,,,,,,,,,,,,LCD_R1,EVENTOUT, +PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT, +PortJ,PJ2,,,,,,,,,,,,,,,LCD_R3,EVENTOUT, +PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT, +PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT, +PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT, +PortJ,PJ6,,,,,,,,,,,,,,,LCD_R7,EVENTOUT, +PortJ,PJ7,,,,,,,,,,,,,,,LCD_G0,EVENTOUT, +PortJ,PJ8,,,,,,,,,,,,,,,LCD_G1,EVENTOUT, +PortJ,PJ9,,,,,,,,,,,,,,,LCD_G2,EVENTOUT, +PortJ,PJ10,,,,,,,,,,,,,,,LCD_G3,EVENTOUT, +PortJ,PJ11,,,,,,,,,,,,,,,LCD_G4,EVENTOUT, +PortJ,PJ12,,,,,,,,,,,,,,,LCD_B0,EVENTOUT, +PortJ,PJ13,,,,,,,,,,,,,,,LCD_B1,EVENTOUT, +PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT, +PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT, +PortK,PK0,,,,,,,,,,,,,,,LCD_G5,EVENTOUT, +PortK,PK1,,,,,,,,,,,,,,,LCD_G6,EVENTOUT, +PortK,PK2,,,,,,,,,,,,,,,LCD_G7,EVENTOUT, +PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT, +PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT, +PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT, +PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT, +PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT, From 5de55e8fb441ba80a4c59a6dbf1bf8978b82eae5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Jan 2020 20:46:10 +1100 Subject: [PATCH 0924/1299] drivers/cyw43: Include stdio.h in files that use printf. --- drivers/cyw43/cyw43_ctrl.c | 1 + drivers/cyw43/cyw43_lwip.c | 1 + drivers/cyw43/cywbt.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/cyw43/cyw43_ctrl.c b/drivers/cyw43/cyw43_ctrl.c index 53601dac22839..efd750e632d89 100644 --- a/drivers/cyw43/cyw43_ctrl.c +++ b/drivers/cyw43/cyw43_ctrl.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include #include "py/mphal.h" diff --git a/drivers/cyw43/cyw43_lwip.c b/drivers/cyw43/cyw43_lwip.c index 391dfbe9007c6..f3ca59e3a4bf8 100644 --- a/drivers/cyw43/cyw43_lwip.c +++ b/drivers/cyw43/cyw43_lwip.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include #include "py/mphal.h" diff --git a/drivers/cyw43/cywbt.c b/drivers/cyw43/cywbt.c index 111cff158f4a5..fae661608dc36 100644 --- a/drivers/cyw43/cywbt.c +++ b/drivers/cyw43/cywbt.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include #include "py/runtime.h" From d494e478556579d3b963b1b05ece208b67fa380a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Jan 2020 20:46:35 +1100 Subject: [PATCH 0925/1299] drivers/cyw43: Return early from cyw43_wifi_set_up if wifi_on fails. --- drivers/cyw43/cyw43_ctrl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cyw43/cyw43_ctrl.c b/drivers/cyw43/cyw43_ctrl.c index efd750e632d89..cc1fbecde8a4e 100644 --- a/drivers/cyw43/cyw43_ctrl.c +++ b/drivers/cyw43/cyw43_ctrl.c @@ -456,7 +456,9 @@ void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up) { } else { country = MAKE_COUNTRY(pyb_country_code[0], pyb_country_code[1], 0); } - cyw43_wifi_on(self, country); + if (cyw43_wifi_on(self, country) != 0) { + return; + } cyw43_wifi_pm(self, 10 << 20 | 1 << 16 | 1 << 12 | 20 << 4 | 2); } if (itf == CYW43_ITF_AP) { From 257b17ec10050a2b433b3eaca936818b5e6a67ed Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Jan 2020 20:48:40 +1100 Subject: [PATCH 0926/1299] stm32/sdio: Add support for H7 MCUs. The cyw43 driver on stm32 will now work with H7 MCUs. --- ports/stm32/sdio.c | 79 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/ports/stm32/sdio.c b/ports/stm32/sdio.c index df4aec25e2ee2..12d8326f9a8ef 100644 --- a/ports/stm32/sdio.c +++ b/ports/stm32/sdio.c @@ -62,12 +62,18 @@ void sdio_init(uint32_t irq_pri) { __HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral SDMMC_TypeDef *SDIO = SDMMC1; - SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | 118; // 1-bit, 400kHz + #if defined(STM32F7) + SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | (120 - 2); // 1-bit, 400kHz + #else + SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | (120 / 2); // 1-bit, 400kHz + #endif mp_hal_delay_us(10); SDIO->POWER = 3; // the card is clocked mp_hal_delay_us(10); - SDIO->DCTRL = 1 << 10; // RWMOD is SDIO_CK + SDIO->DCTRL = SDMMC_DCTRL_RWMOD; // RWMOD is SDIO_CK + #if defined(STM32F7) SDIO->CLKCR |= SDMMC_CLKCR_CLKEN; + #endif mp_hal_delay_us(10); __HAL_RCC_DMA2_CLK_ENABLE(); // enable DMA2 peripheral @@ -79,20 +85,28 @@ void sdio_init(uint32_t irq_pri) { } void sdio_deinit(void) { - RCC->APB2ENR &= ~RCC_APB2ENR_SDMMC1EN; // disable SDIO peripheral - RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA2EN; // disable DMA2 peripheral + __HAL_RCC_SDMMC1_CLK_DISABLE(); + #if defined(STM32F7) + __HAL_RCC_DMA2_CLK_DISABLE(); + #endif } void sdio_enable_high_speed_4bit(void) { SDMMC_TypeDef *SDIO = SDMMC1; SDIO->POWER = 0; // power off mp_hal_delay_us(10); + #if defined(STM32F7) SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_WIDBUS_0 | SDMMC_CLKCR_BYPASS /*| SDMMC_CLKCR_PWRSAV*/; // 4-bit, 48MHz + #else + SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_WIDBUS_0; // 4-bit, 48MHz + #endif mp_hal_delay_us(10); SDIO->POWER = 3; // the card is clocked mp_hal_delay_us(10); - SDIO->DCTRL = 1 << 11 | 1 << 10; // SDIOEN, RWMOD is SDIO_CK + SDIO->DCTRL = SDMMC_DCTRL_SDIOEN | SDMMC_DCTRL_RWMOD; // SDIOEN, RWMOD is SDIO_CK + #if defined(STM32F7) SDIO->CLKCR |= SDMMC_CLKCR_CLKEN; + #endif SDIO->MASK = DEFAULT_MASK; mp_hal_delay_us(10); } @@ -108,6 +122,14 @@ void SDMMC1_IRQHandler(void) { sdmmc_irq_state = SDMMC_IRQ_STATE_DONE; return; } + #if defined(STM32H7) + if (!sdmmc_dma) { + while (sdmmc_buf_cur < sdmmc_buf_top && (SDMMC1->STA & SDMMC_STA_DPSMACT) && !(SDMMC1->STA & SDMMC_STA_RXFIFOE)) { + *(uint32_t*)sdmmc_buf_cur = SDMMC1->FIFO; + sdmmc_buf_cur += 4; + } + } + #endif if (sdmmc_buf_cur >= sdmmc_buf_top) { // data transfer finished, so we are done SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; @@ -115,7 +137,16 @@ void SDMMC1_IRQHandler(void) { return; } if (sdmmc_write) { - SDMMC1->DCTRL = (sdmmc_block_size_log2 << 4) | 1 | (1 << 11) | (!sdmmc_write << 1) | (sdmmc_dma << 3) | (0 << 10); + SDMMC1->DCTRL = + SDMMC_DCTRL_SDIOEN + | SDMMC_DCTRL_RWMOD + | sdmmc_block_size_log2 << SDMMC_DCTRL_DBLOCKSIZE_Pos + #if defined(STM32F7) + | (sdmmc_dma << SDMMC_DCTRL_DMAEN_Pos) + #endif + | (!sdmmc_write) << SDMMC_DCTRL_DTDIR_Pos + | SDMMC_DCTRL_DTEN + ; if (!sdmmc_dma) { SDMMC1->MASK |= SDMMC_MASK_TXFIFOHEIE; } @@ -125,6 +156,7 @@ void SDMMC1_IRQHandler(void) { // data transfer complete // note: it's possible to get DATAEND before CMDREND SDMMC1->ICR = SDMMC_ICR_DATAENDC; + #if defined(STM32F7) // check if there is some remaining data in RXFIFO if (!sdmmc_dma) { while (SDMMC1->STA & SDMMC_STA_RXDAVL) { @@ -132,6 +164,7 @@ void SDMMC1_IRQHandler(void) { sdmmc_buf_cur += 4; } } + #endif if (sdmmc_irq_state == SDMMC_IRQ_STATE_CMD_DONE) { // command and data finished, so we are done SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; @@ -177,9 +210,11 @@ void SDMMC1_IRQHandler(void) { } int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) { + #if defined(STM32F7) // Wait for any outstanding TX to complete while (SDMMC1->STA & SDMMC_STA_TXACT) { } + #endif DMA2_Stream3->CR = 0; // ensure DMA is reset SDMMC1->ICR = SDMMC_STATIC_FLAGS; // clear interrupts @@ -226,9 +261,11 @@ int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) { } int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf) { + #if defined(STM32F7) // Wait for any outstanding TX to complete while (SDMMC1->STA & SDMMC_STA_TXACT) { } + #endif // for SDIO_BYTE_MODE the SDIO chuck of data must be a single block of the length of buf int block_size_log2 = 0; @@ -264,8 +301,10 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le if (dma) { // prepare DMA so it's ready when the DPSM starts its transfer + #if defined(STM32F7) // enable DMA2 peripheral in case it was turned off by someone else RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; + #endif if (write) { // make sure cache is flushed to RAM so the DMA can read the correct data @@ -276,6 +315,7 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le MP_HAL_CLEANINVALIDATE_DCACHE(buf, len); } + #if defined(STM32F7) DMA2->LIFCR = 0x3f << 22; DMA2_Stream3->FCR = 0x07; // ? DMA2_Stream3->PAR = (uint32_t)&SDMMC1->FIFO; @@ -297,6 +337,14 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le | 1 << 5 // PFCTRL periph is flow controller | 1 << 0 // EN ; + #else + SDMMC1->IDMABASE0 = (uint32_t)buf; + SDMMC1->IDMACTRL = SDMMC_IDMA_IDMAEN; + #endif + } else { + #if defined(STM32H7) + SDMMC1->IDMACTRL = 0; + #endif } // for reading, need to initialise the DPSM before starting the CPSM @@ -304,7 +352,16 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le // (and in case we get a long-running unrelated IRQ here on the host just // after writing to CMD to initiate the command) if (!write) { - SDMMC1->DCTRL = (block_size_log2 << 4) | 1 | (1 << 11) | (!write << 1) | (dma << 3); + SDMMC1->DCTRL = + SDMMC_DCTRL_SDIOEN + | SDMMC_DCTRL_RWMOD + | block_size_log2 << SDMMC_DCTRL_DBLOCKSIZE_Pos + #if defined(STM32F7) + | (dma << SDMMC_DCTRL_DMAEN_Pos) + #endif + | (!write) << SDMMC_DCTRL_DTDIR_Pos + | SDMMC_DCTRL_DTEN + ; } SDMMC1->ARG = arg; @@ -328,7 +385,11 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le } if (mp_hal_ticks_ms() - start > 200) { SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; + #if defined(STM32F7) printf("sdio_transfer_cmd53: timeout wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR); + #else + printf("sdio_transfer_cmd53: timeout wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x IDMA=%08x\n", write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->DCTRL, (uint)SDMMC1->IDMACTRL); + #endif return -MP_ETIMEDOUT; } } @@ -336,7 +397,11 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le SDMMC1->MASK &= SDMMC_MASK_SDIOITIE; if (sdmmc_error) { + #if defined(STM32F7) printf("sdio_transfer_cmd53: error=%08lx wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", sdmmc_error, write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR); + #else + printf("sdio_transfer_cmd53: error=%08lx wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x IDMA=%08x\n", sdmmc_error, write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->DCTRL, (uint)SDMMC1->IDMACTRL); + #endif return -(0x1000000 | sdmmc_error); } From 03b73ce329d6e46465942f4baa6ba5e2e27467bd Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Jan 2020 20:49:59 +1100 Subject: [PATCH 0927/1299] stm32/stm32_it: Don't call __HAL_USB_HS_EXTI_CLEAR_FLAG on H7 MCUs. It doesn't exist on these MCUs. --- ports/stm32/stm32_it.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index e77642b8ea3ea..1a2227217bbc8 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -415,8 +415,10 @@ void OTG_HS_WKUP_IRQHandler(void) { OTG_CMD_WKUP_Handler(&pcd_hs_handle); + #if !defined(STM32H7) /* Clear EXTI pending Bit*/ __HAL_USB_HS_EXTI_CLEAR_FLAG(); + #endif IRQ_EXIT(OTG_HS_WKUP_IRQn); } From 2c8c2b935ee94091664781027ab2be9292446cb2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Jan 2020 23:20:42 +1100 Subject: [PATCH 0928/1299] stm32/powerctrl: Improve support for changing system freq on H7 MCUs. This commit improves pllvalues.py to generate PLL values for H7 MCUs that are valid (VCO in and out are in range) and extend for the entire range of SYSCLK values up to 400MHz (up to 480MHz is currently unsupported). --- ports/stm32/Makefile | 2 +- ports/stm32/boards/pllvalues.py | 134 +++++++++++++++++++++++--------- ports/stm32/modmachine.c | 5 ++ ports/stm32/powerctrl.c | 127 +++++++++++++++++++++++++----- 4 files changed, 213 insertions(+), 55 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 96f10fe98a792..11db9dfbabf0b 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -649,7 +649,7 @@ CMSIS_MCU_HDR = $(CMSIS_DIR)/$(CMSIS_MCU_LOWER).h modmachine.c: $(GEN_PLLFREQTABLE_HDR) $(GEN_PLLFREQTABLE_HDR): $(PLLVALUES) | $(HEADER_BUILD) $(ECHO) "GEN $@" - $(Q)$(PYTHON) $(PLLVALUES) -c $(if $(filter $(MCU_SERIES),f7),--relax-pll48,) file:$(BOARD_DIR)/stm32$(MCU_SERIES)xx_hal_conf.h > $@ + $(Q)$(PYTHON) $(PLLVALUES) -c -m $(MCU_SERIES) file:$(BOARD_DIR)/stm32$(MCU_SERIES)xx_hal_conf.h > $@ $(BUILD)/modstm.o: $(GEN_STMCONST_HDR) # Use a pattern rule here so that make will only call make-stmconst.py once to diff --git a/ports/stm32/boards/pllvalues.py b/ports/stm32/boards/pllvalues.py index 4a85b5478a78a..2d64876b46c67 100644 --- a/ports/stm32/boards/pllvalues.py +++ b/ports/stm32/boards/pllvalues.py @@ -7,6 +7,36 @@ from __future__ import print_function import re +class MCU: + def __init__(self, range_sysclk, range_m, range_n, range_p, range_q, range_vco_in, range_vco_out): + self.range_sysclk = range_sysclk + self.range_m = range_m + self.range_n = range_n + self.range_p = range_p + self.range_q = range_q + self.range_vco_in = range_vco_in + self.range_vco_out = range_vco_out + +mcu_default = MCU( + range_sysclk=range(2, 216 + 1, 2), + range_m=range(2, 63 + 1), + range_n=range(192, 432 + 1), + range_p=range(2, 8 + 1, 2), + range_q=range(2, 15 + 1), + range_vco_in=range(1, 2 + 1), + range_vco_out=range(192, 432 + 1), +) + +mcu_h7 = MCU( + range_sysclk=range(2, 400 + 1, 2), # above 400MHz currently unsupported + range_m=range(1, 63 + 1), + range_n=range(4, 512 + 1), + range_p=range(2, 128 + 1, 2), + range_q=range(1, 128 + 1), + range_vco_in=range(1, 16 + 1), + range_vco_out=range(150, 960 + 1), # 150-420=medium, 192-960=wide +) + def close_int(x): return abs(x - round(x)) < 0.01 @@ -42,41 +72,40 @@ def compute_pll(hse, sys): # improved version that doesn't require N/M to be an integer def compute_pll2(hse, sys, relax_pll48): # Loop over the allowed values of P, looking for a valid PLL configuration - # that gives the desired "sys" frequency. We use floats for P to force - # floating point arithmetic on Python 2. + # that gives the desired "sys" frequency. fallback = None - for P in (2.0, 4.0, 6.0, 8.0): - NbyM = sys * P / hse + for P in mcu.range_p: # VCO_OUT must be between 192MHz and 432MHz - if not (192 <= hse * NbyM <= 432): + if not sys * P in mcu.range_vco_out: continue + NbyM = float(sys * P) / hse # float for Python 2 # scan M - M = int(192 // NbyM) # starting value - while 2 * M < hse: - M += 1 - # VCO_IN must be between 1MHz and 2MHz (2MHz recommended) - for M in range(M, hse + 1): - if NbyM * M < 191.99 or not close_int(NbyM * M): - continue + M_min = mcu.range_n[0] // int(round(NbyM)) # starting value + while mcu.range_vco_in[-1] * M_min < hse: + M_min += 1 + # VCO_IN must be >=1MHz, but higher is better for stability so start high (low M) + for M in range(M_min, hse + 1): # compute N N = NbyM * M # N must be an integer if not close_int(N): continue + N = round(N) # N is restricted - if not (192 <= N <= 432): + if N not in mcu.range_n: continue - Q = (sys * P / 48) + Q = float(sys * P) / 48 # float for Python 2 # Q must be an integer in a set range - if not (2 <= Q <= 15): - continue - if not close_int(Q): - if int(M) == int(hse) and fallback is None: - # the values don't give 48MHz on PLL48 but are otherwise OK - fallback = M, N, P, int(Q) + if close_int(Q) and round(Q) in mcu.range_q: + # found valid values + return (M, N, P, Q) + # Re-try Q to get at most 48MHz + Q = (sys * P + 47) // 48 + if Q not in mcu.range_q: continue - # found valid values - return (M, N, P, Q) + if fallback is None: + # the values don't give 48MHz on PLL48 but are otherwise OK + fallback = M, N, P, Q if relax_pll48: # might have found values which don't give 48MHz on PLL48 return fallback @@ -85,6 +114,7 @@ def compute_pll2(hse, sys, relax_pll48): return None def compute_derived(hse, pll): + hse = float(hse) # float for Python 2 M, N, P, Q = pll vco_in = hse / M vco_out = hse * N / M @@ -103,16 +133,16 @@ def verify_pll(hse, pll): assert close_int(Q) # verify range - assert 2 <= M <= 63 - assert 192 <= N <= 432 - assert P in (2, 4, 6, 8) - assert 2 <= Q <= 15 - assert 1 <= vco_in <= 2 - assert 192 <= vco_out <= 432 + assert M in mcu.range_m + assert N in mcu.range_n + assert P in mcu.range_p + assert Q in mcu.range_q + assert mcu.range_vco_in[0] <= vco_in <= mcu.range_vco_in[-1] + assert mcu.range_vco_out[0] <= vco_out <= mcu.range_vco_out[-1] def compute_pll_table(source_clk, relax_pll48): valid_plls = [] - for sysclk in range(2, 217, 2): + for sysclk in mcu.range_sysclk: pll = compute_pll2(source_clk, sysclk, relax_pll48) if pll is not None: verify_pll(source_clk, pll) @@ -121,10 +151,34 @@ def compute_pll_table(source_clk, relax_pll48): def generate_c_table(hse, valid_plls): valid_plls.sort() + if mcu.range_sysclk[-1] <= 0xff and mcu.range_m[-1] <= 0x3f and mcu.range_p[-1] // 2 - 1 <= 0x3: + typedef = 'uint16_t' + sys_mask = 0xff + m_shift = 10 + m_mask = 0x3f + p_shift = 8 + p_mask = 0x3 + else: + typedef = 'uint32_t' + sys_mask = 0xffff + m_shift = 24 + m_mask = 0xff + p_shift = 16 + p_mask = 0xff + print("#define PLL_FREQ_TABLE_SYS(pll) ((pll) & %d)" % (sys_mask,)) + print("#define PLL_FREQ_TABLE_M(pll) (((pll) >> %d) & %d)" % (m_shift, m_mask)) + print("#define PLL_FREQ_TABLE_P(pll) (((((pll) >> %d) & %d) + 1) * 2)" % (p_shift, p_mask)) + print("typedef %s pll_freq_table_t;" % (typedef,)) print("// (M, P/2-1, SYS) values for %u MHz source" % hse) - print("static const uint16_t pll_freq_table[%u] = {" % len(valid_plls)) + print("static const pll_freq_table_t pll_freq_table[%u] = {" % (len(valid_plls),)) for sys, (M, N, P, Q) in valid_plls: - print(" (%u << 10) | (%u << 8) | %u," % (M, P // 2 - 1, sys)) + print(" (%u << %u) | (%u << %u) | %u," % (M, m_shift, P // 2 - 1, p_shift, sys), end='') + if M >= 2: + vco_in, vco_out, pllck, pll48ck = compute_derived(hse, (M, N, P, Q)) + print(" // M=%u N=%u P=%u Q=%u vco_in=%.2f vco_out=%.2f pll48=%.2f" + % (M, N, P, Q, vco_in, vco_out, pll48ck), end='' + ) + print() print("};") def print_table(hse, valid_plls): @@ -157,6 +211,7 @@ def search_header_for_hsx_values(filename, vals): return vals def main(): + global mcu global out_format # parse input args @@ -164,7 +219,7 @@ def main(): argv = sys.argv[1:] c_table = False - relax_pll48 = False + mcu_series = 'f4' hse = None hsi = None @@ -172,14 +227,14 @@ def main(): if argv[0] == '-c': c_table = True argv.pop(0) - elif argv[0] == '--relax-pll48': - relax_pll48 = True + elif argv[0] == '-m': argv.pop(0) + mcu_series = argv.pop(0).lower() else: break if len(argv) != 1: - print("usage: pllvalues.py [-c] ") + print("usage: pllvalues.py [-c] [-m ] ") sys.exit(1) if argv[0].startswith("file:"): @@ -194,6 +249,15 @@ def main(): # HSE given directly as an integer hse = int(argv[0]) + # Select MCU parameters + if mcu_series == 'h7': + mcu = mcu_h7 + else: + mcu = mcu_default + + # Relax constraight on PLLQ being 48MHz on F7 and H7 MCUs, which have separate PLLs for 48MHz + relax_pll48 = mcu_series in ('f7', 'h7') + hse_valid_plls = compute_pll_table(hse, relax_pll48) if hsi is not None: hsi_valid_plls = compute_pll_table(hsi, relax_pll48) diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 7db8e29643c47..19f58a98db7f9 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -310,6 +310,11 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { #else mp_int_t sysclk = mp_obj_get_int(args[0]); mp_int_t ahb = sysclk; + #if defined (STM32H7) + if (ahb > 200000000) { + ahb /= 2; + } + #endif mp_int_t apb1 = ahb / 4; mp_int_t apb2 = ahb / 2; if (n_args > 1) { diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 4c40cffb60c27..9619e0ea47302 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -93,12 +93,48 @@ void powerctrl_check_enter_bootloader(void) { #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32WB) +typedef struct _sysclk_scaling_table_entry_t { + uint16_t mhz; + uint16_t value; +} sysclk_scaling_table_entry_t; + +#if defined(STM32F7) +STATIC const sysclk_scaling_table_entry_t volt_scale_table[] = { + { 151, PWR_REGULATOR_VOLTAGE_SCALE3 }, + { 180, PWR_REGULATOR_VOLTAGE_SCALE2 }, + // Above 180MHz uses default PWR_REGULATOR_VOLTAGE_SCALE1 +}; +#elif defined(STM32H7) +STATIC const sysclk_scaling_table_entry_t volt_scale_table[] = { + // See table 55 "Kernel clock distribution overview" of RM0433. + {200, PWR_REGULATOR_VOLTAGE_SCALE3}, + {300, PWR_REGULATOR_VOLTAGE_SCALE2}, + // Above 300MHz uses default PWR_REGULATOR_VOLTAGE_SCALE1 + // (above 400MHz needs special handling for overdrive, currently unsupported) +}; +#endif + +STATIC int powerctrl_config_vos(uint32_t sysclk_mhz) { + #if defined(STM32F7) || defined(STM32H7) + uint32_t volt_scale = PWR_REGULATOR_VOLTAGE_SCALE1; + for (int i = 0; i < MP_ARRAY_SIZE(volt_scale_table); ++i) { + if (sysclk_mhz <= volt_scale_table[i].mhz) { + volt_scale = volt_scale_table[i].value; + break; + } + } + if (HAL_PWREx_ControlVoltageScaling(volt_scale) != HAL_OK) { + return -MP_EIO; + } + #endif + return 0; +} + // Assumes that PLL is used as the SYSCLK source int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) { uint32_t flash_latency; #if defined(STM32F7) - if (need_pllsai) { // Configure PLLSAI at 48MHz for those peripherals that need this freq // (calculation assumes it can get an integral value of PLLSAIN) @@ -118,20 +154,16 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk } RCC->DCKCFGR2 |= RCC_DCKCFGR2_CK48MSEL; } + #endif // If possible, scale down the internal voltage regulator to save power - uint32_t volt_scale; - if (sysclk_mhz <= 151) { - volt_scale = PWR_REGULATOR_VOLTAGE_SCALE3; - } else if (sysclk_mhz <= 180) { - volt_scale = PWR_REGULATOR_VOLTAGE_SCALE2; - } else { - volt_scale = PWR_REGULATOR_VOLTAGE_SCALE1; - } - if (HAL_PWREx_ControlVoltageScaling(volt_scale) != HAL_OK) { - return -MP_EIO; + int ret = powerctrl_config_vos(sysclk_mhz); + if (ret) { + return ret; } + #if defined(STM32F7) + // These flash_latency values assume a supply voltage between 2.7V and 3.6V if (sysclk_mhz <= 30) { flash_latency = FLASH_LATENCY_0; @@ -172,6 +204,17 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { + #if defined(STM32H7) + if (wanted_div <= 1) { return RCC_HCLK_DIV1; } + else if (wanted_div <= 2) { return RCC_HCLK_DIV2; } + else if (wanted_div <= 4) { return RCC_HCLK_DIV4; } + else if (wanted_div <= 8) { return RCC_HCLK_DIV8; } + else if (wanted_div <= 16) { return RCC_HCLK_DIV16; } + else if (wanted_div <= 64) { return RCC_HCLK_DIV64; } + else if (wanted_div <= 128) { return RCC_HCLK_DIV128; } + else if (wanted_div <= 256) { return RCC_HCLK_DIV256; } + else { return RCC_HCLK_DIV512; } + #else if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; } else if (wanted_div <= 2) { return RCC_SYSCLK_DIV2; } else if (wanted_div <= 4) { return RCC_SYSCLK_DIV4; } @@ -181,14 +224,35 @@ STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { else if (wanted_div <= 128) { return RCC_SYSCLK_DIV128; } else if (wanted_div <= 256) { return RCC_SYSCLK_DIV256; } else { return RCC_SYSCLK_DIV512; } + #endif } -STATIC uint32_t calc_apb_div(uint32_t wanted_div) { +STATIC uint32_t calc_apb1_div(uint32_t wanted_div) { + #if defined(STM32H7) + if (wanted_div <= 1) { return RCC_APB1_DIV1; } + else if (wanted_div <= 2) { return RCC_APB1_DIV2; } + else if (wanted_div <= 4) { return RCC_APB1_DIV4; } + else if (wanted_div <= 8) { return RCC_APB1_DIV8; } + else { return RCC_APB1_DIV16; } + #else if (wanted_div <= 1) { return RCC_HCLK_DIV1; } else if (wanted_div <= 2) { return RCC_HCLK_DIV2; } else if (wanted_div <= 4) { return RCC_HCLK_DIV4; } else if (wanted_div <= 8) { return RCC_HCLK_DIV8; } - else { return RCC_SYSCLK_DIV16; } + else { return RCC_HCLK_DIV16; } + #endif +} + +STATIC uint32_t calc_apb2_div(uint32_t wanted_div) { + #if defined(STM32H7) + if (wanted_div <= 1) { return RCC_APB2_DIV1; } + else if (wanted_div <= 2) { return RCC_APB2_DIV2; } + else if (wanted_div <= 4) { return RCC_APB2_DIV4; } + else if (wanted_div <= 8) { return RCC_APB2_DIV8; } + else { return RCC_APB2_DIV16; } + #else + return calc_apb1_div(wanted_div); + #endif } int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t apb2) { @@ -207,11 +271,11 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t // Search for a valid PLL configuration that keeps USB at 48MHz uint32_t sysclk_mhz = sysclk / 1000000; - for (const uint16_t *pll = &pll_freq_table[MP_ARRAY_SIZE(pll_freq_table) - 1]; pll >= &pll_freq_table[0]; --pll) { - uint32_t sys = *pll & 0xff; + for (const pll_freq_table_t *pll = &pll_freq_table[MP_ARRAY_SIZE(pll_freq_table) - 1]; pll >= &pll_freq_table[0]; --pll) { + uint32_t sys = PLL_FREQ_TABLE_SYS(*pll); if (sys <= sysclk_mhz) { - m = (*pll >> 10) & 0x3f; - p = ((*pll >> 7) & 0x6) + 2; + m = PLL_FREQ_TABLE_M(*pll); + p = PLL_FREQ_TABLE_P(*pll); if (m == 0) { // special entry for using HSI directly sysclk_source = RCC_SYSCLKSOURCE_HSI; @@ -259,8 +323,13 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t #if !defined(STM32H7) ahb = sysclk >> AHBPrescTable[RCC_ClkInitStruct.AHBCLKDivider >> RCC_CFGR_HPRE_Pos]; #endif - RCC_ClkInitStruct.APB1CLKDivider = calc_apb_div(ahb / apb1); - RCC_ClkInitStruct.APB2CLKDivider = calc_apb_div(ahb / apb2); + RCC_ClkInitStruct.APB1CLKDivider = calc_apb1_div(ahb / apb1); + RCC_ClkInitStruct.APB2CLKDivider = calc_apb2_div(ahb / apb2); + #if defined(STM32H7) + RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; + RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; + #endif #if MICROPY_HW_CLK_LAST_FREQ // Save the bus dividers for use later @@ -294,6 +363,26 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t RCC_OscInitStruct.PLL.PLLN = n; RCC_OscInitStruct.PLL.PLLP = p; RCC_OscInitStruct.PLL.PLLQ = q; + + #if defined(STM32H7) + RCC_OscInitStruct.PLL.PLLR = 0; + if (MICROPY_HW_CLK_VALUE / 1000000 <= 2 * m) { + RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_0; // 1-2MHz + } else if (MICROPY_HW_CLK_VALUE / 1000000 <= 4 * m) { + RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1; // 2-4MHz + } else if (MICROPY_HW_CLK_VALUE / 1000000 <= 8 * m) { + RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2; // 4-8MHz + } else { + RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3; // 8-16MHz + } + if (MICROPY_HW_CLK_VALUE / 1000000 * n <= 420 * m) { + RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOMEDIUM; // 150-420MHz + } else { + RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; // 192-960MHz + } + RCC_OscInitStruct.PLL.PLLFRACN = 0; + #endif + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { return -MP_EIO; } From af88e70414061d868a248d1735f26e645d36844c Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Jan 2020 23:23:56 +1100 Subject: [PATCH 0929/1299] stm32/powerctrl: Reenable PLL3 on H7 MCUs when waking from stop mode. So that USB can work. --- ports/stm32/powerctrl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 9619e0ea47302..0b26e2aea2ae6 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -504,6 +504,13 @@ void powerctrl_enter_stop_mode(void) { } #endif + #if defined(STM32H7) + // Enable PLL3 for USB + RCC->CR |= RCC_CR_PLL3ON; + while (!(RCC->CR & RCC_CR_PLL3RDY)) { + } + #endif + #if defined(STM32L4) // Enable PLLSAI1 for peripherals that use it RCC->CR |= RCC_CR_PLLSAI1ON; From e3ff52863ba927b75fce1b219145f921134b49f6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Jan 2020 23:54:11 +1100 Subject: [PATCH 0930/1299] esp8266/modules/ntptime.py: Add comment about configuring NTP host. The ability to change the host is a frequently requested feature, so explicitly document how it can be achieved using the existing code. See issues #2121, #4385, #4622, #5122, #5536. --- ports/esp8266/modules/ntptime.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp8266/modules/ntptime.py b/ports/esp8266/modules/ntptime.py index 1a1da65357b9b..0f512100c8f0f 100644 --- a/ports/esp8266/modules/ntptime.py +++ b/ports/esp8266/modules/ntptime.py @@ -10,6 +10,7 @@ # (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 NTP_DELTA = 3155673600 +# The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org' host = "pool.ntp.org" def time(): From 3e1bbeabafc08ec0c9b6349b416aed306ef8a7c8 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 24 Jan 2020 15:23:44 -0600 Subject: [PATCH 0931/1299] py/modthread: Fix spelling error in comment. --- py/modthread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/modthread.c b/py/modthread.c index 91237a72b3758..5a9aba55f148a 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -249,7 +249,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) } } - // copy agross the positional arguments + // copy across the positional arguments th_args->n_args = pos_args_len; memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t)); From 83afd48ad93e162eec65d34c2dfe266c995fbafd Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 28 Dec 2019 20:38:27 +0100 Subject: [PATCH 0932/1299] tools/pyboard.py: Add option --no-follow to detach after sending script. This option makes pyboard.py exit as soon as the script/command is successfully sent to the device, ie it does not wait for any output. This can help to avoid hangs if the board is being rebooted with --comman (for example). Example usage: $ python3 ./tools/pyboard.py --device /dev/ttyUSB0 --no-follow \ --command 'import machine; machine.reset()' --- tools/pyboard.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 2a255e91c0753..f1ccc59b9ef0a 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -520,7 +520,9 @@ def main(): cmd_parser.add_argument('-p', '--password', default='python', help='the telnet login password') cmd_parser.add_argument('-c', '--command', help='program passed in as string') cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available') - cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]') + group = cmd_parser.add_mutually_exclusive_group() + group.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]') + group.add_argument('--no-follow', action='store_true', help='Do not follow the output after running the scripts.') cmd_parser.add_argument('-f', '--filesystem', action='store_true', help='perform a filesystem action') cmd_parser.add_argument('files', nargs='*', help='input files') args = cmd_parser.parse_args() @@ -545,7 +547,11 @@ def main(): def execbuffer(buf): try: - ret, ret_err = pyb.exec_raw(buf, timeout=None, data_consumer=stdout_write_bytes) + if args.no_follow: + pyb.exec_raw_no_follow(buf) + ret_err = None + else: + ret, ret_err = pyb.exec_raw(buf, timeout=None, data_consumer=stdout_write_bytes) except PyboardError as er: print(er) pyb.close() From 1cadb12d1c4baefd65a7e1030356b63cc0f6c3a6 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 28 Jan 2020 20:55:44 +0100 Subject: [PATCH 0933/1299] tools/pyboard.py: Use slice del instead of list.clear() for Py2 compat. Python 2 does not have list.clear(). --- tools/pyboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index f1ccc59b9ef0a..51806a3299f03 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -567,7 +567,7 @@ def execbuffer(buf): # do filesystem commands, if given if args.filesystem: filesystem_command(pyb, args.files) - args.files.clear() + del args.files[:] # run the command, if given if args.command is not None: From 1604606238ae7dbb1ead582172d84d23d885eaf8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 30 Jan 2020 18:15:02 +0100 Subject: [PATCH 0934/1299] tools/pyboard.py: Change shebang to use python3. This script still works with Python 2 but Python 3 is recommended. --- tools/pyboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pyboard.py b/tools/pyboard.py index 51806a3299f03..a0b4ac32005cc 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # This file is part of the MicroPython project, http://micropython.org/ # From 61f64c78a6c3ebfe42292b0ff9c93442883f5f0d Mon Sep 17 00:00:00 2001 From: caochaowu Date: Wed, 29 Jan 2020 22:07:48 +0800 Subject: [PATCH 0935/1299] nrf/boards/common.ld: Add ENTRY(Reset_Handler) in linker script. It's not strictly needed but can be helpful when using a debugger. --- ports/nrf/boards/common.ld | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/nrf/boards/common.ld b/ports/nrf/boards/common.ld index 6edd33cf0178a..d2e5eef7627fd 100644 --- a/ports/nrf/boards/common.ld +++ b/ports/nrf/boards/common.ld @@ -1,3 +1,5 @@ +ENTRY(Reset_Handler) + /* define output sections */ SECTIONS { From 4ab8bee82f7d095c10c624de93da12a7aa1af8fd Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 29 Jan 2020 11:23:59 -0600 Subject: [PATCH 0936/1299] unix/main: Print usage and NLR errors to stderr instead of stdout. When stdout is redirected it is useful to have errors printed to stderr instead of being redirected. mp_stderr_print() can't be used in these two instances since the MicroPython runtime is not running so we use fprintf(stderr) instead. --- ports/unix/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/unix/main.c b/ports/unix/main.c index fcf8b1558c613..e12915454428c 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -391,7 +391,7 @@ STATIC void pre_process_options(int argc, char **argv) { #endif } else { invalid_arg: - printf("Invalid option\n"); + fprintf(stderr, "Invalid option\n"); exit(usage(argv)); } a++; @@ -709,6 +709,6 @@ uint mp_import_stat(const char *path) { #endif void nlr_jump_fail(void *val) { - printf("FATAL: uncaught NLR %p\n", val); + fprintf(stderr, "FATAL: uncaught NLR %p\n", val); exit(1); } From c4ea4c1810cac0725b348d77322abc5ba5b1ac80 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Fri, 24 Jan 2020 07:14:24 -0800 Subject: [PATCH 0937/1299] docs/esp8266: In TCP tutorial, add HTTP response code and content-type. Show how to send an HTTP response code and content-type. Without the response code Safari/iOS will fail. Without the content-type Lynx/Links will fail. --- docs/esp8266/tutorial/network_tcp.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/esp8266/tutorial/network_tcp.rst b/docs/esp8266/tutorial/network_tcp.rst index d479f62e6ab87..18916884e45fb 100644 --- a/docs/esp8266/tutorial/network_tcp.rst +++ b/docs/esp8266/tutorial/network_tcp.rst @@ -118,5 +118,6 @@ that contains a table with the state of all the GPIO pins:: break rows = ['%s%d' % (str(p), p.value()) for p in pins] response = html % '\n'.join(rows) + cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') cl.send(response) cl.close() From c25e12d0dd2b1b8a9fdc1231a1377f7983b41ccb Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Mon, 30 Dec 2019 07:22:59 -0600 Subject: [PATCH 0938/1299] zephyr: Update include paths for Zephyr v2.0. Zephyr restructured its includes in v2.0 and removed compatibility shims after two releases in commit 1342dadc365ee22199e51779185899ddf7478686. Updates include paths in MicroPython accordingly to fix build errors in the zephyr port. These changes are compatible with Zephyr v2.0 and later. --- ports/zephyr/machine_i2c.c | 2 +- ports/zephyr/machine_pin.c | 2 +- ports/zephyr/modmachine.c | 2 +- ports/zephyr/modzephyr.c | 2 +- ports/zephyr/modzsensor.c | 2 +- ports/zephyr/src/zephyr_getchar.c | 4 ++-- ports/zephyr/src/zephyr_start.c | 2 +- ports/zephyr/uart_core.c | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ports/zephyr/machine_i2c.c b/ports/zephyr/machine_i2c.c index 0a9e9cfaba539..087cf4bead01a 100644 --- a/ports/zephyr/machine_i2c.c +++ b/ports/zephyr/machine_i2c.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include "py/runtime.h" #include "py/gc.h" diff --git a/ports/zephyr/machine_pin.c b/ports/zephyr/machine_pin.c index c4ea328a2a4ba..d15c556eca612 100644 --- a/ports/zephyr/machine_pin.c +++ b/ports/zephyr/machine_pin.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include "py/runtime.h" #include "py/gc.h" diff --git a/ports/zephyr/modmachine.c b/ports/zephyr/modmachine.c index c89529aa9c73d..dd797740a48d0 100644 --- a/ports/zephyr/modmachine.c +++ b/ports/zephyr/modmachine.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "py/obj.h" #include "py/runtime.h" diff --git a/ports/zephyr/modzephyr.c b/ports/zephyr/modzephyr.c index 3d686605d589f..781eb220354a8 100644 --- a/ports/zephyr/modzephyr.c +++ b/ports/zephyr/modzephyr.c @@ -29,7 +29,7 @@ #include #include -#include +#include #include "py/runtime.h" diff --git a/ports/zephyr/modzsensor.c b/ports/zephyr/modzsensor.c index 2630899b04d57..570017b6326a5 100644 --- a/ports/zephyr/modzsensor.c +++ b/ports/zephyr/modzsensor.c @@ -29,7 +29,7 @@ #include "py/runtime.h" #include -#include +#include #if MICROPY_PY_ZSENSOR diff --git a/ports/zephyr/src/zephyr_getchar.c b/ports/zephyr/src/zephyr_getchar.c index 52b3394d0384a..40dc1c3201243 100644 --- a/ports/zephyr/src/zephyr_getchar.c +++ b/ports/zephyr/src/zephyr_getchar.c @@ -15,9 +15,9 @@ */ #include -#include +#include #include -#include +#include #include "zephyr_getchar.h" extern int mp_interrupt_char; diff --git a/ports/zephyr/src/zephyr_start.c b/ports/zephyr/src/zephyr_start.c index 591eec76bb557..2e0993451bde4 100644 --- a/ports/zephyr/src/zephyr_start.c +++ b/ports/zephyr/src/zephyr_start.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ #include -#include +#include #include "zephyr_getchar.h" int real_main(void); diff --git a/ports/zephyr/uart_core.c b/ports/zephyr/uart_core.c index 325e437434cbb..1c9265037405a 100644 --- a/ports/zephyr/uart_core.c +++ b/ports/zephyr/uart_core.c @@ -27,8 +27,8 @@ #include "py/mpconfig.h" #include "src/zephyr_getchar.h" // Zephyr headers -#include -#include +#include +#include /* * Core UART functions to implement for a port From a7663b862ee102e94edcb5e244a9e6d05ccb11ef Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Mon, 30 Dec 2019 07:25:49 -0600 Subject: [PATCH 0939/1299] zephyr: Replace deprecated time conversion macro. The SYS_CLOCK_HW_CYCLES_TO_NS macro was deprecated in zephyr commit 8892406c1de21bd5de5877f39099e3663a5f3af1. This commit updates MicroPython to use the new k_cyc_to_ns_floor64 api and fix build warnings in the zephyr port. This change is compatible with Zephyr v2.1 and later. --- ports/zephyr/mphalport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/zephyr/mphalport.h b/ports/zephyr/mphalport.h index 4388f607dcc3b..594f6a1f69830 100644 --- a/ports/zephyr/mphalport.h +++ b/ports/zephyr/mphalport.h @@ -2,7 +2,7 @@ #include "lib/utils/interrupt_char.h" static inline mp_uint_t mp_hal_ticks_us(void) { - return SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32()) / 1000; + return k_cyc_to_ns_floor64(k_cycle_get_32()) / 1000; } static inline mp_uint_t mp_hal_ticks_ms(void) { From bc3ce86a5ab5bf697e2d7a88940020953cafdb82 Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Mon, 30 Dec 2019 07:29:31 -0600 Subject: [PATCH 0940/1299] zephyr: Remove reference to syscall_macros_h_target. Zephyr removed the build target syscall_macros_h_target in commit f4adf107f31674eb20881531900ff092cc40c07f. Removes reference from MicroPython to fix build errors in the zephyr port. This change is not compatible with zephyr v2.1 or earlier. It will be compatible with Zephyr v2.2 when released. --- ports/zephyr/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/zephyr/Makefile b/ports/zephyr/Makefile index b23ee109360b9..53882f3d264b8 100644 --- a/ports/zephyr/Makefile +++ b/ports/zephyr/Makefile @@ -108,4 +108,4 @@ outdir/$(BOARD)/Makefile: $(CONF_FILE) $(Z_EXPORTS): outdir/$(BOARD)/Makefile make --no-print-directory -C outdir/$(BOARD) outputexports CMAKE_COMMAND=: >$@ - make -C outdir/$(BOARD) syscall_macros_h_target syscall_list_h_target kobj_types_h_target + make -C outdir/$(BOARD) syscall_list_h_target kobj_types_h_target From 122baa678733636336689feeb4e2c8b4807649db Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 15 Jan 2020 12:05:06 -0600 Subject: [PATCH 0941/1299] unix/main: Add support for MICROPYINSPECT environment variable. This adds support for a MICROPYINSPECT environment variable that works exactly like PYTHONINSPECT; per CPython docs: If this is set to a non-empty string it is equivalent to specifying the -i option. This variable can also be modified by Python code using os.environ to force inspect mode on program termination. --- ports/unix/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/unix/main.c b/ports/unix/main.c index e12915454428c..deda8eb708bf7 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -647,6 +647,10 @@ MP_NOINLINE int main_(int argc, char **argv) { } } + const char *inspect_env = getenv("MICROPYINSPECT"); + if (inspect_env && inspect_env[0] != '\0') { + inspect = true; + } if (ret == NOTHING_EXECUTED || inspect) { if (isatty(0)) { prompt_read_history(); From 7c24f5528582ff1f50a0b24dd360e65342b1fd0c Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 15 Jan 2020 12:37:02 -0600 Subject: [PATCH 0942/1299] tests/cmdline/repl_inspect: Add new test for -i option. This adds a new test to verify that the inspect (-i) command line option works. --- tests/cmdline/repl_inspect.py | 2 ++ tests/cmdline/repl_inspect.py.exp | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 tests/cmdline/repl_inspect.py create mode 100644 tests/cmdline/repl_inspect.py.exp diff --git a/tests/cmdline/repl_inspect.py b/tests/cmdline/repl_inspect.py new file mode 100644 index 0000000000000..5a7564a3c2bbb --- /dev/null +++ b/tests/cmdline/repl_inspect.py @@ -0,0 +1,2 @@ +# cmdline: -c print("test") -i +# -c option combined with -i option results in REPL diff --git a/tests/cmdline/repl_inspect.py.exp b/tests/cmdline/repl_inspect.py.exp new file mode 100644 index 0000000000000..59f734b2f6945 --- /dev/null +++ b/tests/cmdline/repl_inspect.py.exp @@ -0,0 +1,6 @@ +test +MicroPython \.\+ version +Use \.\+ +>>> # cmdline: -c print("test") -i +>>> # -c option combined with -i option results in REPL +>>> From c8d2f7838f1d3ffd5e584fc380395516a7d136ec Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 24 Jan 2020 14:37:26 -0600 Subject: [PATCH 0943/1299] docs/unix: Add a new new quickref page for the UNIX port. This adds a new quickstart page for the UNIX port that documents the command line options and environment variables. --- docs/index.rst | 1 + docs/unix/quickref.rst | 89 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 docs/unix/quickref.rst diff --git a/docs/index.rst b/docs/index.rst index c0417c227cbad..f760fa12a080a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,3 +12,4 @@ MicroPython documentation and references esp8266/quickref.rst esp32/quickref.rst wipy/quickref.rst + unix/quickref.rst diff --git a/docs/unix/quickref.rst b/docs/unix/quickref.rst new file mode 100644 index 0000000000000..ea0e6865c1fec --- /dev/null +++ b/docs/unix/quickref.rst @@ -0,0 +1,89 @@ +.. _unix_quickref: + +Quick reference for the UNIX and Windows ports +============================================== + +Command line options +-------------------- + +Usage:: + + micropython [ -i ] [ -O ] [ -v ] [ -X